diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..8bea0aeeb1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,18 @@ +Dockerfile* +.dockerignore + +packages +**/package.tgz +**/target +**/node_modules +**/outputs + +# Noir.js +tooling/noir_js/lib + +# Wasm build artifacts +compiler/wasm/nodejs +compiler/wasm/web +tooling/noirc_abi_wasm/nodejs +tooling/noirc_abi_wasm/web +tooling/noir_js/lib diff --git a/.eslintrc.js b/.eslintrc.js index f47f171561..0f20016d86 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,4 +1,9 @@ module.exports = { + env: { + browser: true, + es6: true, + node: true, + }, root: true, parser: '@typescript-eslint/parser', plugins: ['@typescript-eslint', 'prettier'], diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 5efe115ddc..8e24b6738a 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -4,13 +4,13 @@ description: Installs the workspace's yarn dependencies and caches them runs: using: composite steps: - - name: Cache - uses: actions/cache@v3 - id: cache + - uses: actions/setup-node@v3 + id: node with: - path: "**/node_modules" - key: yarn-v1-${{ hashFiles('**/yarn.lock') }} + node-version: 18.17.1 + cache: 'yarn' + cache-dependency-path: 'yarn.lock' + - name: Install run: yarn --immutable shell: bash - if: steps.cache.outputs.cache-hit != 'true' diff --git a/.github/workflows/acir-artifacts.yml b/.github/workflows/acir-artifacts.yml new file mode 100644 index 0000000000..43d9acfded --- /dev/null +++ b/.github/workflows/acir-artifacts.yml @@ -0,0 +1,107 @@ +name: Build ACIR artifacts + +on: + pull_request: + push: + branches: + - master + +jobs: + check-artifacts-requested: + name: Check if artifacts should be published + runs-on: ubuntu-22.04 + outputs: + publish: ${{ steps.check.outputs.result }} + + steps: + - name: Check if artifacts should be published + id: check + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { REF_NAME } = process.env; + if (REF_NAME == "master") { + console.log(`publish = true`) + return true; + } + + const labels = context.payload.pull_request.labels.map(label => label.name); + const publish = labels.includes('publish-acir'); + + console.log(`publish = ${publish}`) + return publish; + result-encoding: string + env: + REF_NAME: ${{ github.ref_name }} + + build-nargo: + name: Build nargo binary + if: ${{ needs.check-artifacts-requested.outputs.publish == 'true' }} + runs-on: ubuntu-22.04 + needs: [check-artifacts-requested] + 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.71.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@v3 + with: + name: nargo + path: ./dist/* + retention-days: 3 + + auto-pr-rebuild-script: + name: Rebuild ACIR artifacts + needs: [build-nargo] + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v3 + with: + name: nargo + path: ./nargo + + - name: Add Nargo to $PATH + run: | + chmod +x ${{ github.workspace }}/nargo/nargo + echo "${{ github.workspace }}/nargo" >> $GITHUB_PATH + + - name: Run rebuild script + working-directory: test_programs + run: | + chmod +x ./rebuild.sh + ./rebuild.sh + + - name: Upload ACIR artifacts + uses: actions/upload-artifact@v3 + with: + name: acir-artifacts + path: ./test_programs/acir_artifacts + retention-days: 10 diff --git a/.github/workflows/auto-pr-rebuild-script.yml b/.github/workflows/auto-pr-rebuild-script.yml deleted file mode 100644 index 4937de98e0..0000000000 --- a/.github/workflows/auto-pr-rebuild-script.yml +++ /dev/null @@ -1,130 +0,0 @@ -name: Rebuild ACIR artifacts - -on: - pull_request: - push: - branches: - - master - -jobs: - check-artifacts-requested: - name: Check if artifacts should be published - runs-on: ubuntu-22.04 - outputs: - publish: ${{ steps.check.outputs.result }} - - steps: - - name: Check if artifacts should be published - id: check - uses: actions/github-script@v6 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const { REF_NAME } = process.env; - if (REF_NAME == "master") { - console.log(`publish = true`) - return true; - } - - const labels = context.payload.pull_request.labels.map(label => label.name); - const publish = labels.includes('publish-acir'); - - console.log(`publish = ${publish}`) - return publish; - result-encoding: string - env: - REF_NAME: ${{ github.ref_name }} - - build-nargo: - name: Build nargo binary - if: ${{ needs.check-artifacts-requested.outputs.publish == 'true' }} - runs-on: ubuntu-22.04 - needs: [check-artifacts-requested] - 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.71.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@v3 - with: - name: nargo - path: ./dist/* - retention-days: 3 - - auto-pr-rebuild-script: - name: Rebuild ACIR artifacts - needs: [build-nargo] - runs-on: ubuntu-latest - - steps: - - name: Check out code - uses: actions/checkout@v4 - - - name: Download nargo binary - uses: actions/download-artifact@v3 - with: - name: nargo - path: ./nargo - - - name: Add Nargo to $PATH - run: | - chmod +x ${{ github.workspace }}/nargo/nargo - echo "${{ github.workspace }}/nargo" >> $GITHUB_PATH - - - name: Set up Git user (Github Action) - run: | - git config --local user.name kevaundray - git config --local user.email kevtheappdev@gmail.com - - - name: Run rebuild script - working-directory: tooling/nargo_cli/tests - run: | - chmod +x ./rebuild.sh - ./rebuild.sh - - - name: Upload ACIR artifacts - uses: actions/upload-artifact@v3 - with: - name: acir-artifacts - path: ./tooling/nargo_cli/tests/acir_artifacts - retention-days: 10 - - - name: Check for changes in acir_artifacts directory - id: check_changes - if: ${{ github.ref_name }} == "master" - run: | - git diff --quiet tooling/nargo_cli/tests/acir_artifacts/ || echo "::set-output name=changes::true" - - - name: Create or Update PR - if: steps.check_changes.outputs.changes == 'true' - uses: peter-evans/create-pull-request@v3 - with: - token: ${{ secrets.NOIR_REPO_TOKEN }} - commit-message: "chore: update acir artifacts" - title: "chore: Update ACIR artifacts" - body: "Automatic PR to update acir artifacts" - add-paths: tooling/nargo_cli/tests/acir_artifacts/*.gz - labels: "auto-pr" - branch: "auto-pr-rebuild-script-branch" diff --git a/.github/workflows/build-aztec-feature-flag.yml b/.github/workflows/build-aztec-feature-flag.yml deleted file mode 100644 index 888a88a7f8..0000000000 --- a/.github/workflows/build-aztec-feature-flag.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Build with aztec feature flag - -on: - pull_request: - merge_group: - push: - branches: - - master - -# 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: - build-aztec-feature-flag: - name: Test on ${{ matrix.os }} - runs-on: ${{ matrix.runner }} - timeout-minutes: 30 - - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu - runner: ubuntu-latest - target: x86_64-unknown-linux-gnu - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.71.1 - with: - targets: ${{ matrix.target }} - - - uses: Swatinem/rust-cache@v2 - with: - key: ${{ matrix.target }} - cache-on-failure: true - save-if: ${{ github.event_name != 'merge_group' }} - - - name: Build with feature flag - run: cargo build --features="noirc_frontend/aztec" diff --git a/.github/workflows/docs-new-version.yml b/.github/workflows/docs-new-version.yml deleted file mode 100644 index 9b109e170b..0000000000 --- a/.github/workflows/docs-new-version.yml +++ /dev/null @@ -1,112 +0,0 @@ -name: Cut a new version of the docs - -on: - workflow_dispatch: - inputs: - tag: - description: The tag to build Docs for - required: false - -jobs: - publish-docs: - runs-on: ubuntu-latest - if: ${{ inputs.tag != '' }} - permissions: - pull-requests: write - contents: write - steps: - - name: Checkout sources - uses: actions/checkout@v4 - with: - ref: ${{ inputs.tag }} - - - name: Create new branch - run: | - git checkout -b new-docs-version-${{ github.event.inputs.tag }} - - - name: Setup Node.js - uses: actions/setup-node@v2 - with: - node-version: '18' - - - name: Install wasm-bindgen-cli - uses: taiki-e/install-action@v2 - with: - tool: wasm-bindgen-cli@0.2.86 - - - name: Install wasm-opt - run: | - npm i wasm-opt -g - - - name: Install Yarn - run: npm install -g yarn - - - name: Install Yarn dependencies - run: yarn - - - name: Build acvm_js - run: yarn workspace @noir-lang/acvm_js build - - - name: Build noirc_abi - run: yarn workspace @noir-lang/noirc_abi build - - - 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 - run: | - yarn workspace @noir-lang/noir_js build - - - name: Build docs - run: - yarn workspace docs build - - - name: Cut a new version - working-directory: ./docs - run: yarn docusaurus docs:version ${{ inputs.tag }} - - - name: Remove pre-releases - id: get_version - run: | - cd docs && yarn setStable - - - name: Commit new documentation version - run: | - git config --local user.name 'signorecello' - git config --local user.email 'github@zepedro.me' - git add . - git commit -m "chore(docs): cut new docs version for tag ${{ github.event.inputs.tag }}" - - - name: Push changes to new branch - run: git push origin new-docs-version-${{ github.event.inputs.tag }} - - - name: Create Pull Request - run: | - gh pr create \ - --title "chore(docs): docs for ${{ github.event.inputs.tag }}" \ - --body "Updates documentation to new version for tag ${{ github.event.inputs.tag }}." \ - --base master \ - --head new-docs-version-${{ github.event.inputs.tag }} \ - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Build docs - run: yarn workspace docs build - - - name: Deploy to Netlify - uses: nwtgck/actions-netlify@v2.1 - with: - publish-dir: './docs/build' - production-branch: master - production-deploy: true - github-token: ${{ secrets.GITHUB_TOKEN }} - enable-github-deployment: false - deploy-message: "Deploy from GitHub Actions for tag ${{ inputs.tag }}" - env: - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - timeout-minutes: 1 - diff --git a/.github/workflows/docs-pr.yml b/.github/workflows/docs-pr.yml index 02044c8222..a16487a49e 100644 --- a/.github/workflows/docs-pr.yml +++ b/.github/workflows/docs-pr.yml @@ -55,7 +55,7 @@ jobs: if: needs.add_label.outputs.has_label == 'true' steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v2 @@ -71,34 +71,12 @@ jobs: run: | npm i wasm-opt -g - - name: Install dependencies - run: yarn + - name: Install Yarn dependencies + uses: ./.github/actions/setup - - name: Build acvm_js - run: yarn workspace @noir-lang/acvm_js build - - - name: Build noirc_abi - run: yarn workspace @noir-lang/noirc_abi build - - - 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 - run: | - yarn workspace @noir-lang/noir_js build - - - name: Remove pre-releases - working-directory: docs - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: yarn setStable - - name: Build docs run: - yarn workspace docs build + yarn workspaces foreach -Rt run build - name: Deploy to Netlify uses: nwtgck/actions-netlify@v2.1 diff --git a/.github/workflows/docs-release.yml b/.github/workflows/docs-release.yml deleted file mode 100644 index 4cd9d9998c..0000000000 --- a/.github/workflows/docs-release.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Rebuild docs with the latest release - -on: - release: - types: [released] - workflow_dispatch: - -jobs: - build_and_deploy: - runs-on: ubuntu-latest - permissions: - pull-requests: write - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup Node.js - uses: actions/setup-node@v2 - with: - node-version: '18' - - - name: Install wasm-bindgen-cli - uses: taiki-e/install-action@v2 - with: - tool: wasm-bindgen-cli@0.2.86 - - - name: Install wasm-opt - run: | - npm i wasm-opt -g - - - name: Install dependencies - run: yarn - - - name: Build acvm_js - run: yarn workspace @noir-lang/acvm_js build - - - name: Build noirc_abi - run: yarn workspace @noir-lang/noirc_abi build - - - 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 - run: | - yarn workspace @noir-lang/noir_js build - - - name: Remove pre-releases - working-directory: docs - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: yarn setStable - - - name: Build docs - run: - yarn workspace docs build - - - name: Deploy to Netlify - uses: nwtgck/actions-netlify@v2.1 - with: - publish-dir: './docs/build' - production-branch: master - production-deploy: true - github-token: ${{ secrets.GITHUB_TOKEN }} - enable-github-deployment: false - deploy-message: "Deploy from GitHub Actions for release" - env: - NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - timeout-minutes: 1 diff --git a/.github/workflows/gates_report.yml b/.github/workflows/gates_report.yml index 41a68c6585..8e3ef76882 100644 --- a/.github/workflows/gates_report.yml +++ b/.github/workflows/gates_report.yml @@ -50,9 +50,7 @@ jobs: pull-requests: write steps: - - uses: actions/checkout@v3 - with: - submodules: recursive + - uses: actions/checkout@v4 - name: Download nargo binary uses: actions/download-artifact@v3 @@ -69,10 +67,10 @@ jobs: nargo -V - name: Generate gates report - working-directory: ./tooling/nargo_cli/tests + working-directory: ./test_programs run: | ./gates_report.sh - mv gates_report.json ../../../gates_report.json + mv gates_report.json ../gates_report.json - name: Compare gates reports id: gates_diff diff --git a/.github/workflows/publish-acvm.yml b/.github/workflows/publish-acvm.yml index ded669f13d..06876f27c8 100644 --- a/.github/workflows/publish-acvm.yml +++ b/.github/workflows/publish-acvm.yml @@ -3,7 +3,7 @@ name: Publish ACVM crates on: workflow_dispatch: inputs: - acvm-ref: + noir-ref: description: The acvm reference to checkout required: true @@ -15,7 +15,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 with: - ref: ${{ inputs.acvm-ref }} + ref: ${{ inputs.noir-ref }} - name: Setup toolchain uses: dtolnay/rust-toolchain@1.71.1 diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml new file mode 100644 index 0000000000..4ef7dd8977 --- /dev/null +++ b/.github/workflows/publish-docs.yml @@ -0,0 +1,57 @@ +name: Publish documentation + +on: + workflow_dispatch: + inputs: + noir-ref: + description: The noir reference to checkout + required: false + default: 'master' + +jobs: + publish-docs: + name: Publish docs + runs-on: ubuntu-latest + + steps: + - name: Checkout release branch + uses: actions/checkout@v4 + with: + ref: ${{ inputs.noir-ref }} + token: ${{ secrets.NOIR_RELEASES_TOKEN }} + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '18' + + - name: Install wasm-bindgen-cli + uses: taiki-e/install-action@v2 + with: + tool: wasm-bindgen-cli@0.2.86 + + - name: Install wasm-opt + run: | + npm i wasm-opt -g + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Build docs for deploying + working-directory: docs + run: + yarn workspaces foreach -Rt run build + + - name: Deploy to Netlify + uses: nwtgck/actions-netlify@v2.1 + with: + publish-dir: './docs/build' + production-branch: master + production-deploy: true + github-token: ${{ secrets.GITHUB_TOKEN }} + enable-github-deployment: false + deploy-message: "Deploy from GitHub Actions for tag ${{ inputs.noir-ref }}" + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + timeout-minutes: 1 diff --git a/.github/workflows/publish-es-packages.yml b/.github/workflows/publish-es-packages.yml index 2e88ee2b77..e360654b46 100644 --- a/.github/workflows/publish-es-packages.yml +++ b/.github/workflows/publish-es-packages.yml @@ -30,11 +30,6 @@ jobs: nix-cache-name: "noir" cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - - name: Enable aztec features - if: ${{ inputs.npm-tag == 'aztec' }} - run: | - echo $'\n'"default = [\"aztec\"]"$'\n' >> compiler/noirc_frontend/Cargo.toml - - name: Build wasm package run: | nix build -L .#noir_wasm diff --git a/.github/workflows/publish-nargo.yml b/.github/workflows/publish-nargo.yml index 59d4fe4cc4..3bcc9a1357 100644 --- a/.github/workflows/publish-nargo.yml +++ b/.github/workflows/publish-nargo.yml @@ -30,6 +30,7 @@ jobs: strategy: matrix: target: [x86_64-apple-darwin, aarch64-apple-darwin] + timeout-minutes: 30 steps: - name: Checkout @@ -120,6 +121,7 @@ jobs: fail-fast: false matrix: target: [x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl] + timeout-minutes: 30 steps: - name: Checkout diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 95da6792f0..fcf630345a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,9 +20,39 @@ jobs: 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 + steps: + - name: Checkout release branch + uses: actions/checkout@v4 + with: + ref: ${{ fromJSON(needs.release-please.outputs.release-pr).headBranchName }} + token: ${{ secrets.NOIR_RELEASES_TOKEN }} + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.65.0 + + - name: Update ACVM workspace root versions + run: | + ./scripts/update-acvm-workspace-versions.sh + + - name: Configure git + run: | + git config user.name kevaundray + git config user.email kevtheappdev@gmail.com + + - name: Commit updates + run: | + git add Cargo.toml + git commit -m 'chore: Update root workspace acvm versions' + git push + update-lockfile: name: Update lockfile - needs: [release-please] + needs: [release-please,update-acvm-workspace-package-versions] if: ${{ needs.release-please.outputs.release-pr }} runs-on: ubuntu-latest steps: @@ -49,6 +79,41 @@ jobs: git add Cargo.lock git commit -m 'chore: Update lockfile' git push + + update-docs: + name: Update docs + needs: [release-please, update-lockfile] + if: ${{ needs.release-please.outputs.tag-name }} + runs-on: ubuntu-latest + steps: + - name: Checkout release branch + uses: actions/checkout@v4 + with: + ref: ${{ fromJSON(needs.release-please.outputs.release-pr).headBranchName }} + token: ${{ secrets.NOIR_RELEASES_TOKEN }} + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '18' + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Cut a new version + working-directory: ./docs + run: yarn docusaurus docs:version ${{ needs.release-please.outputs.tag-name }} + + - name: Configure git + run: | + git config --local user.name 'kevaundray' + git config --local user.email 'kevtheappdev@gmail.com' + + - name: Commit new documentation version + run: | + git add . + git commit -m "chore(docs): cut new docs version for tag ${{ needs.release-please.outputs.tag-name }}" + git push build-binaries: name: Build binaries @@ -78,19 +143,33 @@ jobs: ref: master token: ${{ secrets.NOIR_REPO_TOKEN }} inputs: '{ "noir-ref": "${{ needs.release-please.outputs.tag-name }}", "npm-tag": "latest" }' - publish-docs: name: Publish docs needs: [release-please] if: ${{ needs.release-please.outputs.tag-name }} runs-on: ubuntu-latest + steps: - - name: Dispatch to publish workflow + - name: Dispatch to publish-docs uses: benc-uk/workflow-dispatch@v1 with: - workflow: docs-new-version.yml - repo: noir-lang/noir + workflow: publish-docs.yml ref: master - token: ${{ secrets.GITHUB_TOKEN }} - inputs: '{ "tag": "${{ needs.release-please.outputs.tag-name }}"}' + token: ${{ secrets.NOIR_REPO_TOKEN }} + inputs: '{ "noir-ref": "${{ needs.release-please.outputs.tag-name }}" }' + + publish-acvm: + name: Publish acvm + needs: [release-please] + if: ${{ needs.release-please.outputs.tag-name }} + runs-on: ubuntu-latest + + steps: + - name: Dispatch to publish-acvm + uses: benc-uk/workflow-dispatch@v1 + with: + workflow: publish-acvm.yml + ref: master + token: ${{ secrets.NOIR_REPO_TOKEN }} + inputs: '{ "noir-ref": "${{ needs.release-please.outputs.tag-name }}" }' diff --git a/.github/workflows/test-abi_wasm.yml b/.github/workflows/test-abi_wasm.yml deleted file mode 100644 index 52223d874b..0000000000 --- a/.github/workflows/test-abi_wasm.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: ABI Wasm test - -on: - pull_request: - merge_group: - push: - branches: - - master - -# 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: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout sources - uses: actions/checkout@v3 - - - name: Setup Nix - uses: ./.github/actions/nix - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - nix-cache-name: "noir" - cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - - - name: Build noirc_abi_wasm - run: | - nix build -L .#noirc_abi_wasm - cp -r ./result/noirc_abi_wasm/nodejs ./tooling/noirc_abi_wasm - cp -r ./result/noirc_abi_wasm/web ./tooling/noirc_abi_wasm - - - name: Dereference symlink - run: echo "UPLOAD_PATH=$(readlink -f ./result/noirc_abi_wasm)" >> $GITHUB_ENV - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: noirc_abi_wasm - path: ${{ env.UPLOAD_PATH }} - retention-days: 10 - - test: - runs-on: ubuntu-latest - needs: [build] - - steps: - - name: Checkout sources - uses: actions/checkout@v3 - - - name: Download wasm package artifact - uses: actions/download-artifact@v3 - with: - name: noirc_abi_wasm - path: ./tooling/noirc_abi_wasm - - - name: Install Yarn dependencies - uses: ./.github/actions/setup - - - name: Run node tests - run: yarn workspace @noir-lang/noirc_abi test - - - name: Install Playwright - uses: ./.github/actions/install-playwright - - - name: Run browser tests - run: yarn workspace @noir-lang/noirc_abi test:browser - diff --git a/.github/workflows/test-acvm-js.yml b/.github/workflows/test-acvm-js.yml deleted file mode 100644 index 14ce5d916c..0000000000 --- a/.github/workflows/test-acvm-js.yml +++ /dev/null @@ -1,99 +0,0 @@ -name: Test acvm_js - -on: - pull_request: - merge_group: - push: - branches: - - master - -# 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: - build-acvm-js-package: - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - - name: Setup Nix - uses: ./.github/actions/nix - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - nix-cache-name: "noir" - cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - - - name: Build acvm-js - run: | - nix build -L .#acvm_js - - - name: Dereference symlink - run: echo "UPLOAD_PATH=$(readlink -f result)" >> $GITHUB_ENV - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: acvm-js - path: ${{ env.UPLOAD_PATH }} - retention-days: 3 - - test-acvm_js-node: - needs: [build-acvm-js-package] - name: Node.js Tests - runs-on: ubuntu-latest - - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - - name: Download artifact - uses: actions/download-artifact@v3 - with: - name: acvm-js - path: ./result - - - name: Move build artifacts - run: | - mv ./result/acvm_js/nodejs ./acvm-repo/acvm_js/nodejs - mv ./result/acvm_js/web ./acvm-repo/acvm_js/web - - - name: Set up test environment - uses: ./.github/actions/setup - - - name: Run node tests - run: yarn workspace @noir-lang/acvm_js test - - test-acvm_js-browser: - needs: [build-acvm-js-package] - name: Browser Tests - runs-on: ubuntu-latest - - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - - name: Download artifact - uses: actions/download-artifact@v3 - with: - name: acvm-js - path: ./result - - - name: Move build artifacts - run: | - mv ./result/acvm_js/nodejs ./acvm-repo/acvm_js/nodejs - mv ./result/acvm_js/web ./acvm-repo/acvm_js/web - - - name: Set up test environment - uses: ./.github/actions/setup - - - name: Install playwright deps - run: | - npx playwright install - npx playwright install-deps - - - name: Run browser tests - working-directory: ./acvm-repo/acvm_js - run: yarn workspace @noir-lang/acvm_js test:browser diff --git a/.github/workflows/test-cargo.yml b/.github/workflows/test-cargo.yml new file mode 100644 index 0000000000..8d414daa75 --- /dev/null +++ b/.github/workflows/test-cargo.yml @@ -0,0 +1,51 @@ +name: Test cargo + +on: + pull_request: + merge_group: + push: + branches: + - master + +# 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: + build: + name: Test cargo + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Get current date + id: date + run: echo "date=$(date +'%Y.%m.%d.%H.%M')" >> $GITHUB_STATE + - name: prepare docker images tags + id: prep + run: | + REGISTRY="ghcr.io" + IMG="${REGISTRY}/${{ github.repository }}" + IMAGE=$(echo "$IMG" | tr '[:upper:]' '[:lower:]') + TAGS="${IMAGE}:${{ github.sha }}" + TAGS="${TAGS},${IMAGE}:latest,${IMAGE}:v${{ steps.date.outputs.date }}" + echo ::set-output name=tags::${TAGS} + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v3 + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Test cargo + uses: docker/build-push-action@v5 + with: + context: . + file: Dockerfile.ci + tags: ${{ steps.prep.outputs.tags }} + target: test-cargo + cache-from: type=gha + cache-to: type=gha,mode=max \ No newline at end of file diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml deleted file mode 100644 index ad28d9c8e8..0000000000 --- a/.github/workflows/test-integration.yml +++ /dev/null @@ -1,199 +0,0 @@ -name: test-integration - -on: - workflow_dispatch: - pull_request: - merge_group: - schedule: - - cron: "0 2 * * *" # Run nightly at 2 AM UTC - -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.71.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@v3 - with: - name: nargo - path: ./dist/* - retention-days: 3 - - build-acvm-js: - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - - name: Setup Nix - uses: ./.github/actions/nix - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - nix-cache-name: "noir" - cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - - - name: Build acvm-js - run: | - nix build -L .#acvm_js - - - name: Dereference symlink - run: echo "UPLOAD_PATH=$(readlink -f result/acvm_js)" >> $GITHUB_ENV - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: acvm-js - path: ${{ env.UPLOAD_PATH }} - retention-days: 3 - - build-wasm: - runs-on: ubuntu-latest - - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - - name: Setup Nix - uses: ./.github/actions/nix - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - nix-cache-name: "noir" - cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - - - name: Build wasm package - run: | - nix build -L .#noir_wasm - - - name: Dereference symlink - run: echo "UPLOAD_PATH=$(readlink -f ./result/noir_wasm)" >> $GITHUB_ENV - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: noir_wasm - path: ${{ env.UPLOAD_PATH }} - retention-days: 3 - - build-noirc: - runs-on: ubuntu-latest - - steps: - - name: Checkout sources - uses: actions/checkout@v3 - - - name: Setup Nix - uses: ./.github/actions/nix - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - nix-cache-name: "noir" - cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - - - name: Build noirc_abi_wasm - run: | - nix build -L .#noirc_abi_wasm - cp -r ./result/noirc_abi_wasm/nodejs ./tooling/noirc_abi_wasm - cp -r ./result/noirc_abi_wasm/web ./tooling/noirc_abi_wasm - - - name: Dereference symlink - run: echo "UPLOAD_PATH=$(readlink -f ./result/noirc_abi_wasm)" >> $GITHUB_ENV - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: noirc_abi_wasm - path: ${{ env.UPLOAD_PATH }} - retention-days: 10 - - test-solidity-verifier: - runs-on: ubuntu-latest - needs: [build-acvm-js, build-wasm, build-nargo, build-noirc] - env: - CACHED_PATH: /tmp/nix-cache - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Download nargo binary - uses: actions/download-artifact@v3 - with: - name: nargo - path: ./nargo - - - name: Download acvm_js package artifact - uses: actions/download-artifact@v3 - with: - name: acvm-js - path: ./acvm-repo/acvm_js - - - name: Download noir_wasm package artifact - uses: actions/download-artifact@v3 - with: - name: noir_wasm - path: ./compiler/wasm - - - name: Download noirc_abi package artifact - uses: actions/download-artifact@v3 - with: - name: noirc_abi_wasm - path: ./tooling/noirc_abi_wasm - - - 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: Install Yarn dependencies - uses: ./.github/actions/setup - - - name: Install Playwright - uses: ./.github/actions/install-playwright - - - name: Setup `integration-tests` - run: | - yarn workspace @noir-lang/source-resolver build - yarn workspace @noir-lang/types build - yarn workspace @noir-lang/backend_barretenberg build - yarn workspace @noir-lang/noir_js build - - - name: Run `integration-tests` - run: | - yarn test:integration - - - name: Alert on nightly test failure - uses: JasonEtco/create-an-issue@v2 - if: ${{ failure() && github.event_name == 'schedule' }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - WORKFLOW_NAME: ${{ github.workflow }} - WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - with: - update_existing: true - filename: .github/NIGHTLY_TEST_FAILURE.md diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml new file mode 100644 index 0000000000..a298d67a48 --- /dev/null +++ b/.github/workflows/test-js-packages.yml @@ -0,0 +1,440 @@ +name: Javascript Tests + +on: + pull_request: + merge_group: + push: + branches: + - master + +# 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: + build-nargo: + runs-on: ubuntu-22.04 + timeout-minutes: 30 + + steps: + - name: Checkout Noir repo + uses: actions/checkout@v4 + + - name: Setup toolchain + uses: dtolnay/rust-toolchain@1.71.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 + 7z a -ttar -so -an ./dist/* | 7z a -si ./nargo-x86_64-unknown-linux-gnu.tar.gz + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: nargo + path: ./dist/* + retention-days: 3 + + build-noir-wasm: + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Setup Nix + uses: ./.github/actions/nix + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + nix-cache-name: "noir" + cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} + + - name: Build wasm package + run: | + nix build -L .#noir_wasm + + - name: Dereference symlink + run: echo "UPLOAD_PATH=$(readlink -f ./result/noir_wasm)" >> $GITHUB_ENV + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: noir_wasm + path: ${{ env.UPLOAD_PATH }} + retention-days: 3 + + + build-acvm-js: + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Setup Nix + uses: ./.github/actions/nix + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + nix-cache-name: "noir" + cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} + + - name: Build acvm-js + run: | + nix build -L .#acvm_js + + - name: Dereference symlink + run: echo "UPLOAD_PATH=$(readlink -f result/acvm_js)" >> $GITHUB_ENV + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: acvm-js + path: ${{ env.UPLOAD_PATH }} + retention-days: 3 + + build-noirc-abi: + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Setup Nix + uses: ./.github/actions/nix + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + nix-cache-name: "noir" + cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} + + - name: Build noirc_abi_wasm + run: | + nix build -L .#noirc_abi_wasm + + - name: Dereference symlink + run: echo "UPLOAD_PATH=$(readlink -f ./result/noirc_abi_wasm)" >> $GITHUB_ENV + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: noirc_abi_wasm + path: ${{ env.UPLOAD_PATH }} + retention-days: 10 + + test-acvm_js-node: + needs: [build-acvm-js] + name: ACVM JS (Node.js) + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Download artifact + uses: actions/download-artifact@v3 + with: + name: acvm-js + path: ./acvm-repo/acvm_js + + - name: Set up test environment + uses: ./.github/actions/setup + + - name: Run node tests + run: yarn workspace @noir-lang/acvm_js test + + test-acvm_js-browser: + needs: [build-acvm-js] + name: ACVM JS (Browser) + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Download artifact + uses: actions/download-artifact@v3 + with: + name: acvm-js + path: ./acvm-repo/acvm_js + + - name: Set up test environment + uses: ./.github/actions/setup + + - name: Install playwright deps + run: | + npx playwright install + npx playwright install-deps + + - name: Run browser tests + run: yarn workspace @noir-lang/acvm_js test:browser + + test-noirc-abi: + needs: [build-noirc-abi] + name: noirc_abi + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Download wasm package artifact + uses: actions/download-artifact@v3 + with: + name: noirc_abi_wasm + path: ./tooling/noirc_abi_wasm + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Run node tests + run: yarn workspace @noir-lang/noirc_abi test + + - name: Install Playwright + uses: ./.github/actions/install-playwright + + - name: Run browser tests + run: yarn workspace @noir-lang/noirc_abi test:browser + + test-noir-js-backend-barretenberg: + needs: [build-noirc-abi] + name: noir-js-backend-barretenberg + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download wasm package artifact + uses: actions/download-artifact@v3 + with: + name: noirc_abi_wasm + path: ./tooling/noirc_abi_wasm + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Build noir_js_types + run: yarn workspace @noir-lang/types build + + - name: Run barretenberg wrapper tests + run: | + yarn workspace @noir-lang/backend_barretenberg test + + test-noir-js: + needs: [build-acvm-js, build-noirc-abi] + name: Noir JS + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download artifact + uses: actions/download-artifact@v3 + with: + name: acvm-js + path: ./acvm-repo/acvm_js + + - name: Download wasm package artifact + uses: actions/download-artifact@v3 + with: + name: noirc_abi_wasm + path: ./tooling/noirc_abi_wasm + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - 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 + yarn workspace @noir-lang/noir_js test + + test-noir-wasm: + needs: [build-noir-wasm, build-nargo] + name: noir_wasm + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Download wasm package artifact + uses: actions/download-artifact@v3 + with: + name: noir_wasm + path: ./compiler/wasm + + - name: Download nargo binary + uses: actions/download-artifact@v3 + with: + name: nargo + path: ./nargo + + - name: Compile fixtures with Nargo CLI + working-directory: ./compiler/wasm/fixtures + run: | + nargo_binary=${{ github.workspace }}/nargo/nargo + chmod +x $nargo_binary + for dir in $(ls -d */); do + pushd $dir/noir-script + $nargo_binary compile + popd + done + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Install Playwright + uses: ./.github/actions/install-playwright + + - name: Run node tests + run: yarn workspace @noir-lang/noir_wasm test:node + + - name: Run browser tests + run: yarn workspace @noir-lang/noir_wasm test:browser + + test-noir-codegen: + needs: [build-acvm-js, build-noirc-abi] + name: noir_codegen + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download acvm_js package artifact + uses: actions/download-artifact@v3 + with: + name: acvm-js + path: ./acvm-repo/acvm_js + + - name: Download noirc_abi package artifact + uses: actions/download-artifact@v3 + with: + name: noirc_abi_wasm + path: ./tooling/noirc_abi_wasm + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Build noir_js_types + run: yarn workspace @noir-lang/types build + + - name: Build noir_js + run: yarn workspace @noir-lang/noir_js build + + - name: Run noir_codegen tests + run: yarn workspace @noir-lang/noir_codegen test + + test-integration: + name: Integration Tests + runs-on: ubuntu-latest + needs: [build-acvm-js, build-noir-wasm, build-nargo, build-noirc-abi] + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download nargo binary + uses: actions/download-artifact@v3 + with: + name: nargo + path: ./nargo + + - name: Download acvm_js package artifact + uses: actions/download-artifact@v3 + with: + name: acvm-js + path: ./acvm-repo/acvm_js + + - name: Download noir_wasm package artifact + uses: actions/download-artifact@v3 + with: + name: noir_wasm + path: ./compiler/wasm + + - name: Download noirc_abi package artifact + uses: actions/download-artifact@v3 + with: + name: noirc_abi_wasm + path: ./tooling/noirc_abi_wasm + + - 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: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Install Playwright + uses: ./.github/actions/install-playwright + + - 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" + yarn workspaces foreach -vtp --from "{$PACKAGES_TO_BUILD}" run build + + - name: Run `integration-tests` + run: | + yarn test:integration + + # 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 + # 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: + - test-acvm_js-node + - test-acvm_js-browser + - test-noirc-abi + - test-noir-js-backend-barretenberg + - test-noir-js + - test-noir-wasm + - test-noir-codegen + - test-integration + + steps: + - name: Report overall success + run: | + if [[ $FAIL == true ]]; then + exit 1 + else + exit 0 + fi + env: + # We treat any skipped or failing jobs as a failure for the workflow as a whole. + FAIL: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'skipped') }} diff --git a/.github/workflows/test-js.yml b/.github/workflows/test-js.yml new file mode 100644 index 0000000000..2f29e02715 --- /dev/null +++ b/.github/workflows/test-js.yml @@ -0,0 +1,52 @@ +name: Test JS packages + +on: + pull_request: + merge_group: + push: + branches: + - master + +# 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: + build: + name: Test JS packages + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Get current date + id: date + run: echo "date=$(date +'%Y.%m.%d.%H.%M')" >> $GITHUB_STATE + - name: prepare docker images tags + id: prep + run: | + REGISTRY="ghcr.io" + IMG="${REGISTRY}/${{ github.repository }}" + IMAGE=$(echo "$IMG" | tr '[:upper:]' '[:lower:]') + TAGS="${IMAGE}:${{ github.sha }}" + TAGS="${TAGS},${IMAGE}:latest,${IMAGE}:v${{ steps.date.outputs.date }}" + echo ::set-output name=tags::${TAGS} + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v3 + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Test JS packages + uses: docker/build-push-action@v5 + with: + context: . + file: Dockerfile.ci + tags: ${{ steps.prep.outputs.tags }} + target: test-js + cache-from: type=gha + cache-to: type=gha,mode=max \ No newline at end of file diff --git a/.github/workflows/test-noir-js.yml b/.github/workflows/test-noir-js.yml deleted file mode 100644 index e74f2ee601..0000000000 --- a/.github/workflows/test-noir-js.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Test Noir Js - -on: - pull_request: - merge_group: - push: - branches: - - master - -jobs: - test-noir-js: - name: Test Noir JS - runs-on: ubuntu-latest - timeout-minutes: 30 - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Install Yarn dependencies - uses: ./.github/actions/setup - - - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.71.1 - with: - targets: wasm32-unknown-unknown - - - uses: Swatinem/rust-cache@v2 - with: - key: wasm32-unknown-unknown-noir-js - cache-on-failure: true - save-if: ${{ github.event_name != 'merge_group' }} - - - name: Install jq - run: sudo apt-get install jq - - - name: Install wasm-bindgen-cli - uses: taiki-e/install-action@v2 - with: - tool: wasm-bindgen-cli@0.2.86 - - - name: Install wasm-opt - run: | - npm i wasm-opt -g - - - name: Build acvm_js - run: yarn workspace @noir-lang/acvm_js build - - - name: Build noirc_abi - run: yarn workspace @noir-lang/noirc_abi build - - - 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 - yarn workspace @noir-lang/noir_js test diff --git a/.github/workflows/test-noir_wasm.yml b/.github/workflows/test-noir_wasm.yml deleted file mode 100644 index 2175e20acd..0000000000 --- a/.github/workflows/test-noir_wasm.yml +++ /dev/null @@ -1,125 +0,0 @@ -name: Wasm - -on: - pull_request: - merge_group: - push: - branches: - - master - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref || github.run_id }} - cancel-in-progress: true - -jobs: - build-nargo: - runs-on: ubuntu-22.04 - 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.71.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@v3 - with: - name: nargo - path: ./dist/* - retention-days: 3 - - build-wasm: - runs-on: ubuntu-latest - - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - - name: Setup Nix - uses: ./.github/actions/nix - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - nix-cache-name: "noir" - cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - - - name: Build wasm package - run: | - nix build -L .#noir_wasm - - - name: Dereference symlink - run: echo "UPLOAD_PATH=$(readlink -f ./result/noir_wasm)" >> $GITHUB_ENV - - - name: Upload artifact - uses: actions/upload-artifact@v3 - with: - name: noir_wasm - path: ${{ env.UPLOAD_PATH }} - retention-days: 3 - - test: - needs: [build-wasm, build-nargo] - name: Test noir_wasm - runs-on: ubuntu-latest - steps: - - name: Checkout noir-lang/noir - uses: actions/checkout@v4 - - - name: Download wasm package artifact - uses: actions/download-artifact@v3 - with: - name: noir_wasm - path: ./compiler/wasm/downloaded - - - name: Download nargo binary - uses: actions/download-artifact@v3 - with: - name: nargo - path: ./nargo - - - name: Compile fixtures with Nargo CLI - working-directory: ./compiler/wasm/fixtures - run: | - nargo_binary=${{ github.workspace }}/nargo/nargo - chmod +x $nargo_binary - for dir in $(ls -d */); do - pushd $dir/noir-script - $nargo_binary compile - popd - done - - - name: Install Yarn dependencies - uses: ./.github/actions/setup - - - name: Install Playwright - uses: ./.github/actions/install-playwright - - - name: Install dependencies - run: | - cp -r ./compiler/wasm/downloaded/nodejs ./compiler/wasm - cp -r ./compiler/wasm/downloaded/web ./compiler/wasm - yarn workspace @noir-lang/source-resolver build - - - name: Run node tests - run: yarn workspace @noir-lang/noir_wasm test:node - - - name: Run browser tests - run: yarn workspace @noir-lang/noir_wasm test:browser diff --git a/.github/workflows/test-source-resolver.yml b/.github/workflows/test-source-resolver.yml deleted file mode 100644 index 5dafe4c5fd..0000000000 --- a/.github/workflows/test-source-resolver.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Test Source Resolver - -on: - push: - paths: - - "compiler/source-resolver/**" - pull_request: - paths: - - "compiler/source-resolver/**" - -jobs: - test: - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Install Yarn dependencies - uses: ./.github/actions/setup - - - name: Build @noir-lang/source-resolver - run: yarn workspace @noir-lang/source-resolver build - - - name: Run tests - run: yarn workspace @noir-lang/source-resolver test diff --git a/.gitignore b/.gitignore index 169353af2b..8d02d34d46 100644 --- a/.gitignore +++ b/.gitignore @@ -14,11 +14,6 @@ pkg/ !.yarn/sdks !.yarn/versions -# Source resolver -compiler/source-resolver/node_modules -compiler/source-resolver/lib -compiler/source-resolver/lib-node - # Noir.js tooling/noir_js/lib @@ -36,9 +31,10 @@ result *.pk *.vk **/Verifier.toml +**/contract **/target -!tooling/nargo_cli/tests/acir_artifacts/*/target -!tooling/nargo_cli/tests/acir_artifacts/*/target/witness.gz +!test_programs/acir_artifacts/*/target +!test_programs/acir_artifacts/*/target/witness.gz !compiler/wasm/noir-script/target gates_report.json @@ -53,3 +49,9 @@ compiler/wasm/web tooling/noirc_abi_wasm/nodejs tooling/noirc_abi_wasm/web tooling/noir_js/lib + +**/package.tgz +packages + +# docs autogen build +/docs/docs/noir_js/reference/ diff --git a/.prettierrc b/.prettierrc index ef937f9697..052c0657b3 100644 --- a/.prettierrc +++ b/.prettierrc @@ -3,4 +3,4 @@ "printWidth": 120, "singleQuote": true, "trailingComma": "all" -} \ No newline at end of file +} diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ea8ab2395d..9e3193c22f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,4 +1,4 @@ { - ".": "0.19.2", - "acvm-repo": "0.33.0" + ".": "0.20.0", + "acvm-repo": "0.37.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index cacf629d81..9abb97f686 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,311 @@ # Changelog +## [0.20.0](https://github.com/noir-lang/noir/compare/v0.19.5...v0.20.0) (2023-12-01) + + +### ⚠ BREAKING CHANGES + +* avoid integer overflows ([#2713](https://github.com/noir-lang/noir/issues/2713)) +* return Pedersen structure in stdlib ([#3190](https://github.com/noir-lang/noir/issues/3190)) +* noir-wasm outputs debug symbols ([#3317](https://github.com/noir-lang/noir/issues/3317)) +* move mimc to hash submodule ([#3361](https://github.com/noir-lang/noir/issues/3361)) +* bump MSRV to 1.71.1 ([#3353](https://github.com/noir-lang/noir/issues/3353)) +* Add semver checks for the compiler version in Nargo.toml ([#3336](https://github.com/noir-lang/noir/issues/3336)) +* Move circuit serialization circuit into acir ([#3345](https://github.com/noir-lang/noir/issues/3345)) +* change stdlib function `pedersen` to `pedersen_commitment` ([#3341](https://github.com/noir-lang/noir/issues/3341)) +* expose pedersen hash in acir and bb solver ([#3269](https://github.com/noir-lang/noir/issues/3269)) +* Switch to new pedersen implementation ([#3151](https://github.com/noir-lang/noir/issues/3151)) +* Pass ACIR to ACVM by reference rather than passing ownership ([#2872](https://github.com/noir-lang/noir/issues/2872)) +* Make for loops a statement ([#2975](https://github.com/noir-lang/noir/issues/2975)) +* **traits:** trait functions with a default implementation must not be followed by a semicolon ([#2987](https://github.com/noir-lang/noir/issues/2987)) +* **wasm:** improve and simplify wasm compiler interface ([#2976](https://github.com/noir-lang/noir/issues/2976)) +* **wasm:** update wasm artifacts to match cli artifacts ([#2973](https://github.com/noir-lang/noir/issues/2973)) +* Maintain shape of foreign call arguments ([#2935](https://github.com/noir-lang/noir/issues/2935)) +* update to `bb` version 0.7.3 ([#2729](https://github.com/noir-lang/noir/issues/2729)) +* **noir_js:** Rename inner and outer proof methods ([#2845](https://github.com/noir-lang/noir/issues/2845)) +* `generateWitness` now returns a serialized witness file ([#2842](https://github.com/noir-lang/noir/issues/2842)) +* Issue an error when a module is declared twice & fix module search path ([#2801](https://github.com/noir-lang/noir/issues/2801)) +* Default integers to u64 ([#2764](https://github.com/noir-lang/noir/issues/2764)) + +### Features + +* `compute_note_hash_and_nullifier` check ([#3216](https://github.com/noir-lang/noir/issues/3216)) ([4963c6c](https://github.com/noir-lang/noir/commit/4963c6c024bba710dd8907147f631f5c26094f0a)) +* **abi:** Throw errors rather than returning string from `noirc_abi_wasm` ([#2817](https://github.com/noir-lang/noir/issues/2817)) ([df7b42c](https://github.com/noir-lang/noir/commit/df7b42cd253d1b908a42c367b116813f9999d93b)) +* **abi:** Tuples as inputs/outputs to main ([#2899](https://github.com/noir-lang/noir/issues/2899)) ([d8bd78f](https://github.com/noir-lang/noir/commit/d8bd78f60c447bb8488a844d779e8aaf4150afe7)) +* **acir:** Enable dynamic indices on non-homogenous arrays ([#2703](https://github.com/noir-lang/noir/issues/2703)) ([622d2e4](https://github.com/noir-lang/noir/commit/622d2e436992c23e6d0885b591bd1072ca57b307)) +* **acir:** Handle dynamic array operations for nested slices ([#3187](https://github.com/noir-lang/noir/issues/3187)) ([e026319](https://github.com/noir-lang/noir/commit/e026319fc25763d30781b90e6a4454ddb5d3bc7b)) +* **acir:** Set dynamic array values ([#3054](https://github.com/noir-lang/noir/issues/3054)) ([e871866](https://github.com/noir-lang/noir/commit/e871866d2203f0f0f49f3b273d99d385b950b65f)) +* **acvm_js:** Export black box solver functions ([#2812](https://github.com/noir-lang/noir/issues/2812)) ([da8a98e](https://github.com/noir-lang/noir/commit/da8a98ed312fe69cb0bdb8f9d0a70ee7a981398f)) +* **acvm:** Separate ACVM optimizations and transformations ([#2979](https://github.com/noir-lang/noir/issues/2979)) ([5865d1a](https://github.com/noir-lang/noir/commit/5865d1a1bca16e1853663c71f893ff81fa3f7185)) +* Add --check option to nargo fmt for dry-run formatting verification ([#3530](https://github.com/noir-lang/noir/issues/3530)) ([4469707](https://github.com/noir-lang/noir/commit/4469707d97085fab0f7ade8d015dc827c56156ee)) +* Add `destroy` method to `Noir` ([#3105](https://github.com/noir-lang/noir/issues/3105)) ([7e40274](https://github.com/noir-lang/noir/commit/7e402744a7d64ffcac6db026cec1631230204f0f)) +* Add `execute` method to `Noir` class ([#3081](https://github.com/noir-lang/noir/issues/3081)) ([17bdd7e](https://github.com/noir-lang/noir/commit/17bdd7e3909f0ddd195e5cb7095cd0d30758ed43)) +* Add `FieldElement::from<usize>` implementation ([#3647](https://github.com/noir-lang/noir/issues/3647)) ([8b7c5aa](https://github.com/noir-lang/noir/commit/8b7c5aa5311f4e6811438f67bd552b641b13fc9a)) +* Add `noir_codegen` package ([#3392](https://github.com/noir-lang/noir/issues/3392)) ([6c4cd4d](https://github.com/noir-lang/noir/commit/6c4cd4d37e4af38dccf899bcbd3950d1e236b35d)) +* Add ACIR serializer C++ codegen ([#2961](https://github.com/noir-lang/noir/issues/2961)) ([7556982](https://github.com/noir-lang/noir/commit/7556982dbebe25eaa17240abbe270b771b55de45)) +* Add an options object to `BarretenbergBackend` constructor ([#3105](https://github.com/noir-lang/noir/issues/3105)) ([7e40274](https://github.com/noir-lang/noir/commit/7e402744a7d64ffcac6db026cec1631230204f0f)) +* Add aztec selectors for event structs ([#2983](https://github.com/noir-lang/noir/issues/2983)) ([982380e](https://github.com/noir-lang/noir/commit/982380e54bb4d696688522c540f1234734ae2e80)) +* Add bb interface implementation ([#2902](https://github.com/noir-lang/noir/issues/2902)) ([fe92dc0](https://github.com/noir-lang/noir/commit/fe92dc0df57b2cbc0e7b8cd1f3a91cba6b0f3049)) +* Add check for overlapping generic traits ([#3307](https://github.com/noir-lang/noir/issues/3307)) ([8cf81b6](https://github.com/noir-lang/noir/commit/8cf81b659bed9522aede29c1ebb4a4ed2bfa1205)) +* Add conditional compilation of methods based on the underlying field being used ([#3045](https://github.com/noir-lang/noir/issues/3045)) ([2e008e2](https://github.com/noir-lang/noir/commit/2e008e2438795bbc41b0641e830378b76bf2e194)) +* Add crate for pub modifier ([#3271](https://github.com/noir-lang/noir/issues/3271)) ([e7a1a1a](https://github.com/noir-lang/noir/commit/e7a1a1a4b42b6b72c16f2204e33af80dbabba6b5)) +* Add debugger commands to introspect (and modify) the current state ([#3391](https://github.com/noir-lang/noir/issues/3391)) ([9e1ad85](https://github.com/noir-lang/noir/commit/9e1ad858cf8a1d9aba0137abe6a749267498bfaf)) +* Add experimental REPL-based debugger ([#2995](https://github.com/noir-lang/noir/issues/2995)) ([281c696](https://github.com/noir-lang/noir/commit/281c696da61c64b42b9525b8756ffc195f70d775)) +* Add exports of JS black box solvers to noirJS ([#3295](https://github.com/noir-lang/noir/issues/3295)) ([8369871](https://github.com/noir-lang/noir/commit/836987150f82354d3dfc01cfaad69f70240ca80c)) +* Add generic count check for trait methods ([#3382](https://github.com/noir-lang/noir/issues/3382)) ([a9f9717](https://github.com/noir-lang/noir/commit/a9f9717ba69c0dd8e4fc7045fe6aea2077b84c95)) +* Add JS types for ABI and input maps ([#3023](https://github.com/noir-lang/noir/issues/3023)) ([599e7a1](https://github.com/noir-lang/noir/commit/599e7a1d6bae5d93273e9ef1265024eac909660d)) +* Add LSP command to profile opcodes in vscode ([#3496](https://github.com/noir-lang/noir/issues/3496)) ([6fbf77a](https://github.com/noir-lang/noir/commit/6fbf77ae2b87a55db92344f5066a82ccaf6c2086)) +* Add lsp formatting ([#3433](https://github.com/noir-lang/noir/issues/3433)) ([286c876](https://github.com/noir-lang/noir/commit/286c87694fda185f25b05cec5504142643bc207f)) +* Add noir types package ([#2893](https://github.com/noir-lang/noir/issues/2893)) ([e8fc868](https://github.com/noir-lang/noir/commit/e8fc8687e6dd89295fd023201443f1197963a243)) +* Add package version to Nargo.toml metadata ([#3427](https://github.com/noir-lang/noir/issues/3427)) ([9e1717c](https://github.com/noir-lang/noir/commit/9e1717c2d96a0b9e394e5cb2fb9e1d09b5259ca0)) +* Add profile info print out ([#3425](https://github.com/noir-lang/noir/issues/3425)) ([a8b5fa8](https://github.com/noir-lang/noir/commit/a8b5fa8e30dc27e64666381b7451569f350967d1)) +* Add semver checks for the compiler version in Nargo.toml ([#3336](https://github.com/noir-lang/noir/issues/3336)) ([0e530cf](https://github.com/noir-lang/noir/commit/0e530cfe86f87a532be30a02f4353d010e47e458)) +* Add special case for boolean AND in acir-gen ([#3615](https://github.com/noir-lang/noir/issues/3615)) ([824039b](https://github.com/noir-lang/noir/commit/824039bcc0a3275f333ea94aecc701d129f99fe5)) +* Add support for tuple values in `noir_codegen` ([#3592](https://github.com/noir-lang/noir/issues/3592)) ([346d75f](https://github.com/noir-lang/noir/commit/346d75f9dd9261996d4d7bb80eb7e4118e8f8ce2)) +* Allow a trait to be implemented multiple times for the same struct ([#3292](https://github.com/noir-lang/noir/issues/3292)) ([51831df](https://github.com/noir-lang/noir/commit/51831df68bc20460c6d05d55469002db06113925)) +* Allow providing custom foreign call executors to `execute_circuit` ([#3506](https://github.com/noir-lang/noir/issues/3506)) ([d27db33](https://github.com/noir-lang/noir/commit/d27db332f8c320ffd9b5520bebbd83ae09e31de7)) +* Allow traits to have generic functions ([#3365](https://github.com/noir-lang/noir/issues/3365)) ([0f9af65](https://github.com/noir-lang/noir/commit/0f9af652efc6b7628784a397a9df674eaa30de61)) +* Avoid integer overflows ([#2713](https://github.com/noir-lang/noir/issues/2713)) ([7d7d632](https://github.com/noir-lang/noir/commit/7d7d63291d712137f97e6d44a774acdf2bd20512)) +* Aztec-packages ([#3599](https://github.com/noir-lang/noir/issues/3599)) ([2cd6dc3](https://github.com/noir-lang/noir/commit/2cd6dc39e3a956aa5dff721d47aaf1921f98fded)) +* Aztec-packages ([#3626](https://github.com/noir-lang/noir/issues/3626)) ([e0a96ea](https://github.com/noir-lang/noir/commit/e0a96ea70b17c8c898dd72ac929f3969a4cec1d3)) +* Cache debug artifacts ([#3133](https://github.com/noir-lang/noir/issues/3133)) ([c5a6229](https://github.com/noir-lang/noir/commit/c5a622983e4049d82589f185be5e96c63ed6066d)) +* Check where clauses when searching for trait impls ([#3407](https://github.com/noir-lang/noir/issues/3407)) ([84c6604](https://github.com/noir-lang/noir/commit/84c6604397f262c09ba4bac157fead38b8280313)) +* Codegen typed interfaces for functions in `noir_codegen` ([#3533](https://github.com/noir-lang/noir/issues/3533)) ([290c463](https://github.com/noir-lang/noir/commit/290c463622a93a34293f73b5bf2aea7ade30a11c)) +* Compile without a backend ([#3437](https://github.com/noir-lang/noir/issues/3437)) ([d69cf5d](https://github.com/noir-lang/noir/commit/d69cf5debcc430bb019b6cc95774aac084776dda)) +* Complex slice inputs for dynamic slice builtins ([#3617](https://github.com/noir-lang/noir/issues/3617)) ([8b23b34](https://github.com/noir-lang/noir/commit/8b23b349ae15afa48f6cbe8962586bbe79e79890)) +* Contract events in artifacts ([#2873](https://github.com/noir-lang/noir/issues/2873)) ([4765c82](https://github.com/noir-lang/noir/commit/4765c8288c583a61a81ff97eea1ef49df13eeca0)) +* Copy on write optimization for brillig ([#3522](https://github.com/noir-lang/noir/issues/3522)) ([da29c02](https://github.com/noir-lang/noir/commit/da29c02327acb2f46f5a7a25c7404dfa44c82616)) +* Data bus ([#3508](https://github.com/noir-lang/noir/issues/3508)) ([6b0bdbc](https://github.com/noir-lang/noir/commit/6b0bdbced1bfe2c92e90dd7b70ca8f9e5ccb7c0d)) +* **debugger:** Highlight current src code loc ([#3174](https://github.com/noir-lang/noir/issues/3174)) ([6b87582](https://github.com/noir-lang/noir/commit/6b87582dfe872ad6c248cf9995d76b0ef1580625)) +* **debugger:** Print limited source code context ([#3217](https://github.com/noir-lang/noir/issues/3217)) ([dcda1c7](https://github.com/noir-lang/noir/commit/dcda1c7aed69ae8f55cd3f680e3cc1ece9de7541)) +* Default integers to u64 ([#2764](https://github.com/noir-lang/noir/issues/2764)) ([01cb041](https://github.com/noir-lang/noir/commit/01cb041a92ef6043dd5a160e0a56a63400801980)) +* Dynamic indexing of non-homogenous slices ([#2883](https://github.com/noir-lang/noir/issues/2883)) ([72c3661](https://github.com/noir-lang/noir/commit/72c3661c86712b99236eafaac99f76f13d42b9d9)) +* Enable the `fmt` command in the help menu ([#3328](https://github.com/noir-lang/noir/issues/3328)) ([63d414c](https://github.com/noir-lang/noir/commit/63d414c06a399525601e3db11dc48b180e93c2d8)) +* Expand trait impl overlap check to cover generic types ([#3320](https://github.com/noir-lang/noir/issues/3320)) ([a01549b](https://github.com/noir-lang/noir/commit/a01549b78a2c5de3e64ce5d3e5c4bb73a8c8b4fb)) +* Export `CompiledCircuit` from codegened TS ([#3589](https://github.com/noir-lang/noir/issues/3589)) ([e06c675](https://github.com/noir-lang/noir/commit/e06c67500da11518caffe0e98bdb9cd7f5f89049)) +* Expose pedersen hash in acir and bb solver ([#3269](https://github.com/noir-lang/noir/issues/3269)) ([0108b6c](https://github.com/noir-lang/noir/commit/0108b6c1e8dc0dfc766ab3c4944deae9354dec36)) +* Extract Brillig VM to allow step debugging ([#3259](https://github.com/noir-lang/noir/issues/3259)) ([f6431f9](https://github.com/noir-lang/noir/commit/f6431f99711f15a96a4f7fed2f413daece94b5e1)) +* Format infix expressions ([#3001](https://github.com/noir-lang/noir/issues/3001)) ([7926ada](https://github.com/noir-lang/noir/commit/7926ada88ed08ac9d874604834533d900fbb16b0)) +* **formatter:** Add formatter support for array literals ([#3061](https://github.com/noir-lang/noir/issues/3061)) ([a535321](https://github.com/noir-lang/noir/commit/a5353217a1f49b83daf11d5fa55e0bcccebf0271)) +* Handle constant index operations on simple slices ([#3464](https://github.com/noir-lang/noir/issues/3464)) ([7ae12f8](https://github.com/noir-lang/noir/commit/7ae12f8c5243d31b2f410c246ed6b9e2fcea5d4c)) +* Handle warnings in evaluator ([#3205](https://github.com/noir-lang/noir/issues/3205)) ([5cfd156](https://github.com/noir-lang/noir/commit/5cfd156ca2035038a226bdd81a51636d3de3c34e)) +* Implement `bound_constraint_with_offset` in terms of `AcirVar`s ([#3233](https://github.com/noir-lang/noir/issues/3233)) ([8d89cb5](https://github.com/noir-lang/noir/commit/8d89cb59fe710859a96eaed4f988952bd727fb7d)) +* Implement automatic dereferencing for index expressions ([#3082](https://github.com/noir-lang/noir/issues/3082)) ([8221bfd](https://github.com/noir-lang/noir/commit/8221bfd2ffde7d1dbf71a72d95257acf76ecca74)) +* Implement automatic dereferencing for indexing lvalues ([#3083](https://github.com/noir-lang/noir/issues/3083)) ([6e2b70a](https://github.com/noir-lang/noir/commit/6e2b70ae90b686158957ea29ef1b2a5f0ed38e5f)) +* Implement euclidean division and signed division in terms of `AcirVar`s ([#3230](https://github.com/noir-lang/noir/issues/3230)) ([b8b7782](https://github.com/noir-lang/noir/commit/b8b77825410c0e1f95549259a51e2c40de1ec342)) +* Implement impl specialization ([#3087](https://github.com/noir-lang/noir/issues/3087)) ([44716fa](https://github.com/noir-lang/noir/commit/44716fae0bae0f78ceee76f7231af49c4abeace1)) +* Implement integer printing ([#3577](https://github.com/noir-lang/noir/issues/3577)) ([6601408](https://github.com/noir-lang/noir/commit/6601408e378b2afe4fdfd8e04482c39311ccc7e9)) +* Implement raw string literals ([#3556](https://github.com/noir-lang/noir/issues/3556)) ([87a302f](https://github.com/noir-lang/noir/commit/87a302fbc26d5fd42694953935d95a7ccb3d50a0)) +* Implement string escape sequences ([#2803](https://github.com/noir-lang/noir/issues/2803)) ([f7529b8](https://github.com/noir-lang/noir/commit/f7529b80f0958fd47a525f25a123f16438bbb892)) +* Implement where clauses on impls ([#3324](https://github.com/noir-lang/noir/issues/3324)) ([4c3d1de](https://github.com/noir-lang/noir/commit/4c3d1dea27726133335538443df3dbbd2c8f2d58)) +* **lsp:** Add "info" codelens ([#2982](https://github.com/noir-lang/noir/issues/2982)) ([80770d9](https://github.com/noir-lang/noir/commit/80770d9fae7c42e69a62cf01babfc69449600ac5)) +* **lsp:** Add goto definition for functions ([#3656](https://github.com/noir-lang/noir/issues/3656)) ([7bb7356](https://github.com/noir-lang/noir/commit/7bb735662c86e6533ac58f448ad748e34f02edb7)) +* Maintain shape of foreign call arguments ([#2935](https://github.com/noir-lang/noir/issues/2935)) ([f7869e6](https://github.com/noir-lang/noir/commit/f7869e6fb492b617e776e538ac4babfa56261d26)) +* Make generic impls callable ([#3297](https://github.com/noir-lang/noir/issues/3297)) ([8d9b738](https://github.com/noir-lang/noir/commit/8d9b738ea958320a16946ebe6fcfb6bbf2dda42e)) +* Manage breakpoints and allow restarting a debugging session ([#3325](https://github.com/noir-lang/noir/issues/3325)) ([f502108](https://github.com/noir-lang/noir/commit/f502108a59e2141f4898b0a25e84d7ed7d2bff58)) +* Nargo test runtime callstacks and assert messages without string matching ([#2953](https://github.com/noir-lang/noir/issues/2953)) ([1b6a4e6](https://github.com/noir-lang/noir/commit/1b6a4e6021929c23a1bca5dff02c004422cc71f8)) +* **noir_js:** Allow providing foreign call handlers in noirJS ([#3294](https://github.com/noir-lang/noir/issues/3294)) ([c76b0f8](https://github.com/noir-lang/noir/commit/c76b0f81b89ae02c39c13c3bd400b5d13f083759)) +* Noir-wasm outputs debug symbols ([#3317](https://github.com/noir-lang/noir/issues/3317)) ([f9933fa](https://github.com/noir-lang/noir/commit/f9933fa50c42aade8ddc13d29deef7645ddcf586)) +* Noir-wasm takes dependency graph ([#3213](https://github.com/noir-lang/noir/issues/3213)) ([a2c8ebd](https://github.com/noir-lang/noir/commit/a2c8ebd4a800d7ef042ac9cbe5ee6a837c715634)) +* Old docs issues ([#3195](https://github.com/noir-lang/noir/issues/3195)) ([26746c5](https://github.com/noir-lang/noir/commit/26746c59e12a60f3869a5b885b05926c94f01215)) +* Optimize euclidean division acir-gen ([#3121](https://github.com/noir-lang/noir/issues/3121)) ([2c175c0](https://github.com/noir-lang/noir/commit/2c175c0d886eea390ef97ada1c2a5b0e1bef15e8)) +* Oracle mocker for nargo test ([#2928](https://github.com/noir-lang/noir/issues/2928)) ([0dd1e77](https://github.com/noir-lang/noir/commit/0dd1e77c0e625805e15fa56b4738c93ebae19b6d)) +* Pass ACIR to ACVM by reference rather than passing ownership ([#2872](https://github.com/noir-lang/noir/issues/2872)) ([b3a9c34](https://github.com/noir-lang/noir/commit/b3a9c343993ce3207de62106bda6cb2b2ef3de50)) +* Pass brillig bytecode to VM by reference ([#3030](https://github.com/noir-lang/noir/issues/3030)) ([4ee290b](https://github.com/noir-lang/noir/commit/4ee290b8b6f75bc1974a5750248570eeca8d244e)) +* Perform compile-time euclidean division on constants ([#3231](https://github.com/noir-lang/noir/issues/3231)) ([3866d7e](https://github.com/noir-lang/noir/commit/3866d7ea32dcdabbdb5ba85478d97fd51a6850f3)) +* Prevent unnecessary witness creation in euclidean division ([#2980](https://github.com/noir-lang/noir/issues/2980)) ([c6f660e](https://github.com/noir-lang/noir/commit/c6f660e86d40a106930483f1d6161814e3c0de10)) +* Properly track equivalence of witnesses generated for black box functions ([#3428](https://github.com/noir-lang/noir/issues/3428)) ([20b70c2](https://github.com/noir-lang/noir/commit/20b70c29b4bd323d67ef56ab1933341a7747d3cb)) +* Provide formatting subcommand ([#2640](https://github.com/noir-lang/noir/issues/2640)) ([a38b15f](https://github.com/noir-lang/noir/commit/a38b15f5d8e69faff125d363f2fd1f2f90ae6830)) +* Publish aztec build of noir_wasm ([#3049](https://github.com/noir-lang/noir/issues/3049)) ([3b51f4d](https://github.com/noir-lang/noir/commit/3b51f4df7e808233f6987baec93f4b5de7e5b304)) +* Refactor debugger and separate core from UI ([#3308](https://github.com/noir-lang/noir/issues/3308)) ([8466810](https://github.com/noir-lang/noir/commit/846681079ab7295b201480a5c8baebc45e858c6f)) +* Remove redundant predicate from brillig quotients ([#2784](https://github.com/noir-lang/noir/issues/2784)) ([a8f18c5](https://github.com/noir-lang/noir/commit/a8f18c55b35f47c6fa3ebfebcd827aeb55e5c850)) +* Remove type arrays for flat slices ([#3466](https://github.com/noir-lang/noir/issues/3466)) ([8225b2b](https://github.com/noir-lang/noir/commit/8225b2b379ddf145f9418f8517478704f9aac350)) +* Remove unnecessary truncation of boolean multiplication ([#3122](https://github.com/noir-lang/noir/issues/3122)) ([39dbcf1](https://github.com/noir-lang/noir/commit/39dbcf1ab80d2bb472d08db4de15d4e0c1f2eb52)) +* Replace boolean range constraints with arithmetic opcodes ([#3234](https://github.com/noir-lang/noir/issues/3234)) ([949222c](https://github.com/noir-lang/noir/commit/949222c20d9e65152e3814d02da1c4c41ffc23a5)) +* Return compilation errors from noir_wasm ([#3091](https://github.com/noir-lang/noir/issues/3091)) ([55f63c9](https://github.com/noir-lang/noir/commit/55f63c935cec62fbba63eed421812a4372c1aa4d)) +* Return Pedersen structure in stdlib ([#3190](https://github.com/noir-lang/noir/issues/3190)) ([be30d59](https://github.com/noir-lang/noir/commit/be30d59e61a9dff6ab94ffb97365c1282c331643)) +* Reuse witnesses more when interacting with memory ([#3658](https://github.com/noir-lang/noir/issues/3658)) ([5a4a73d](https://github.com/noir-lang/noir/commit/5a4a73d24ddd7d2bb46c85714397ee6e031c97a6)) +* Reuse witnesses which have been assigned constant values during ACIR gen ([#3137](https://github.com/noir-lang/noir/issues/3137)) ([9eb43e2](https://github.com/noir-lang/noir/commit/9eb43e2a4665397295e74a593f73d19fa9fa5d27)) +* Save Brillig execution state in ACVM ([#3026](https://github.com/noir-lang/noir/issues/3026)) ([88682da](https://github.com/noir-lang/noir/commit/88682da87ffc9e26da5c9e4b5a4d8e62a6ee43c6)) +* Send and receive unflattened public inputs to backend ([#3543](https://github.com/noir-lang/noir/issues/3543)) ([a7bdc67](https://github.com/noir-lang/noir/commit/a7bdc67ef3ec2037bffc4f1f472907cad786c319)) +* Solve `fixed_base_scalar_mul` black box functions in rust ([#3153](https://github.com/noir-lang/noir/issues/3153)) ([1c1afbc](https://github.com/noir-lang/noir/commit/1c1afbcddf0b5fdb39f00ad28ae90caf699d1265)) +* **ssa:** Multiple slice mergers ([#2753](https://github.com/noir-lang/noir/issues/2753)) ([8f76fe5](https://github.com/noir-lang/noir/commit/8f76fe5819e95ed111587090e15add48a2b4e859)) +* **stdlib:** Optimize constraint counts in sha256/sha512 ([#3253](https://github.com/noir-lang/noir/issues/3253)) ([d3be552](https://github.com/noir-lang/noir/commit/d3be552149ab375b24b509603fcd7237b374ca5a)) +* Switch to new pedersen implementation ([#3151](https://github.com/noir-lang/noir/issues/3151)) ([35fb3f7](https://github.com/noir-lang/noir/commit/35fb3f7076d52db7ca3bef0a70a3dbccaf82f58d)) +* **traits:** Add impl Trait as function return type [#2397](https://github.com/noir-lang/noir/issues/2397) ([#3176](https://github.com/noir-lang/noir/issues/3176)) ([4cb2024](https://github.com/noir-lang/noir/commit/4cb20244abba0abc49be0376611979a786563565)) +* **traits:** Add trait impl for buildin types ([#2964](https://github.com/noir-lang/noir/issues/2964)) ([2c87b27](https://github.com/noir-lang/noir/commit/2c87b273dfdf033dd8c79b78f006a0e9813559d7)) +* **traits:** Added checks for duplicated trait associated items (types, consts, functions) ([#2927](https://github.com/noir-lang/noir/issues/2927)) ([d49492c](https://github.com/noir-lang/noir/commit/d49492cd80d04ee6acc01247b06b088deefcd0c6)) +* **traits:** Allow multiple traits to share the same associated function name and to be implemented for the same type ([#3126](https://github.com/noir-lang/noir/issues/3126)) ([004f8dd](https://github.com/noir-lang/noir/commit/004f8dd733cb23da4ed57b160f6b86d53bc0b5f1)) +* **traits:** Implement trait bounds typechecker + monomorphizer passes ([#2717](https://github.com/noir-lang/noir/issues/2717)) ([5ca99b1](https://github.com/noir-lang/noir/commit/5ca99b128e9991b5272c00292208d85415e70edf)) +* **traits:** Improve support for traits static method resolution ([#2958](https://github.com/noir-lang/noir/issues/2958)) ([0d0d8f7](https://github.com/noir-lang/noir/commit/0d0d8f7d2b401eb6b534dbb175dfd4b26d2a5f7d)) +* **traits:** Multi module support for traits ([#2844](https://github.com/noir-lang/noir/issues/2844)) ([4deb07f](https://github.com/noir-lang/noir/commit/4deb07f80ce110187b66a46dd5624af3b8df3dbd)) +* Use ranges instead of a vector for input witness ([#3314](https://github.com/noir-lang/noir/issues/3314)) ([b12b7ec](https://github.com/noir-lang/noir/commit/b12b7ecb995988c731be5f1f2f67fda952f1a228)) +* **wasm:** Improve and simplify wasm compiler interface ([#2976](https://github.com/noir-lang/noir/issues/2976)) ([1b5124b](https://github.com/noir-lang/noir/commit/1b5124bc74f7ac5360db04b34d1b7b2284061fd3)) +* **wasm:** Update wasm artifacts to match cli artifacts ([#2973](https://github.com/noir-lang/noir/issues/2973)) ([ce16c0b](https://github.com/noir-lang/noir/commit/ce16c0b14565cfe1bc2c9f09ae71643d2657440b)) + + +### Bug Fixes + +* "Missing trait impl" error in trait dispatch ([#3440](https://github.com/noir-lang/noir/issues/3440)) ([52daaec](https://github.com/noir-lang/noir/commit/52daaec504101fe3c0caa30441c17f30a34af475)) +* `compute_note_hash_and_nullifier` compiler check ([#3351](https://github.com/noir-lang/noir/issues/3351)) ([4e2d35f](https://github.com/noir-lang/noir/commit/4e2d35f256bea2fee3a6cbd7af0c0c15a37c0a2e)) +* **3275:** Activate brillig modulo test with negative integers ([#3318](https://github.com/noir-lang/noir/issues/3318)) ([31c493c](https://github.com/noir-lang/noir/commit/31c493ce2082a571d147f707837beb4f3ed2ca64)) +* **3300:** Cache warnings into debug artefacts ([#3313](https://github.com/noir-lang/noir/issues/3313)) ([cb5a15b](https://github.com/noir-lang/noir/commit/cb5a15b9dbcfdaac5d656a122c73dca23855307d)) +* ACIR optimizer should update assertion messages ([#3010](https://github.com/noir-lang/noir/issues/3010)) ([758b6b6](https://github.com/noir-lang/noir/commit/758b6b62918907c1a39f3090a77419003551745e)) +* **acvm:** Return false rather than panicking on invalid ECDSA signatures ([#2783](https://github.com/noir-lang/noir/issues/2783)) ([155abc0](https://github.com/noir-lang/noir/commit/155abc0d99fff41c79163c16bf297d41e5dff0fa)) +* Add `pub` modifier to grumpkin functions ([#3036](https://github.com/noir-lang/noir/issues/3036)) ([f8990d7](https://github.com/noir-lang/noir/commit/f8990d75b948ce0a6968db659370f7ece7f5db08)) +* Add compiler error message for invalid input types ([#3220](https://github.com/noir-lang/noir/issues/3220)) ([989e80d](https://github.com/noir-lang/noir/commit/989e80d4ea62e68cfab69a1cd16d481cbccc6c02)) +* Add size checks to integer literals ([#3236](https://github.com/noir-lang/noir/issues/3236)) ([7f8fe8c](https://github.com/noir-lang/noir/commit/7f8fe8c88eb2d26ae3a93e2f74430fadc74b4836)) +* Adding proving key initialization ([#3322](https://github.com/noir-lang/noir/issues/3322)) ([3383740](https://github.com/noir-lang/noir/commit/3383740f9a0004f2ee77c9686f81baed6cd1917c)) +* Allow `where` clause on all functions and improve error message ([#3465](https://github.com/noir-lang/noir/issues/3465)) ([1647e33](https://github.com/noir-lang/noir/commit/1647e33564bf56ab8721a365f5fc6bcb38901412)) +* Allow constructors in parentheses in `if` conditions and `for` ranges ([#3219](https://github.com/noir-lang/noir/issues/3219)) ([ad192d1](https://github.com/noir-lang/noir/commit/ad192d1b7492f6ecd5fc98bb88201d6c442dc052)) +* Allow two `TypeVariable::Constant(N)` to unify even if their constants are not equal ([#3225](https://github.com/noir-lang/noir/issues/3225)) ([cc4ca4b](https://github.com/noir-lang/noir/commit/cc4ca4bb5f4fed5f531a2040501fcc6ed53a9ab4)) +* Apply predicate to over/underflow checks ([#3494](https://github.com/noir-lang/noir/issues/3494)) ([fc3edf7](https://github.com/noir-lang/noir/commit/fc3edf7aa5da9074614fa900bbcb57e512e3d56b)) +* **aztec_nr:** Serialise arrays of structs ([#3401](https://github.com/noir-lang/noir/issues/3401)) ([e979a58](https://github.com/noir-lang/noir/commit/e979a587e755d4b715ebacba715d778938026ac0)) +* Change non-constant argument errors from `to_be_radix` from ICE to proper error ([#3048](https://github.com/noir-lang/noir/issues/3048)) ([19ce286](https://github.com/noir-lang/noir/commit/19ce28638fe3ea42ab4984cb99e3898cd17fa8d9)) +* Check for overflow with hexadecimal inputs ([#3004](https://github.com/noir-lang/noir/issues/3004)) ([db1e736](https://github.com/noir-lang/noir/commit/db1e736240c0b74f6f59504db5a50de1c749d395)) +* Compiler version error message ([#3558](https://github.com/noir-lang/noir/issues/3558)) ([026a358](https://github.com/noir-lang/noir/commit/026a3587b01ddc8f444ff588a7b3f3fd1a0bb386)) +* Complete debug metadata ([#3228](https://github.com/noir-lang/noir/issues/3228)) ([2f6509d](https://github.com/noir-lang/noir/commit/2f6509d2acdee5014d65efaca9e6a9e0df3ca160)) +* Conditionally run the "Create or Update PR" step in acir artifacts rebuild workflow ([#2849](https://github.com/noir-lang/noir/issues/2849)) ([63da875](https://github.com/noir-lang/noir/commit/63da875a85a2ad4ad3038443ba52eb28ea44ad10)) +* Corrected the formatting of error message parameters in index out of bounds error ([#3630](https://github.com/noir-lang/noir/issues/3630)) ([3bba386](https://github.com/noir-lang/noir/commit/3bba3862dc8703410681300be894bfd1ebca7336)) +* **debugger:** Step through foreign calls and breakpoints inside Brillig blocks ([#3511](https://github.com/noir-lang/noir/issues/3511)) ([5d77d7a](https://github.com/noir-lang/noir/commit/5d77d7ac82a4df6995ca151b2c8070044cb1fe9d)) +* Determinism of fallback transformer ([#3100](https://github.com/noir-lang/noir/issues/3100)) ([12daad1](https://github.com/noir-lang/noir/commit/12daad19c902caf5ee9e2eb4b6847bde5a924353)) +* Disable modulo for fields ([#3009](https://github.com/noir-lang/noir/issues/3009)) ([7e68976](https://github.com/noir-lang/noir/commit/7e689768f4af1188e01a1a300a0d2fa152cea504)) +* Disallow returning constant values ([#2978](https://github.com/noir-lang/noir/issues/2978)) ([79c2e88](https://github.com/noir-lang/noir/commit/79c2e88ebefe71ebc0fe457347570df31b24ac36)) +* Do not perform dead instruction elimination on mod,div unless rhs is constant ([#3141](https://github.com/noir-lang/noir/issues/3141)) ([af3d771](https://github.com/noir-lang/noir/commit/af3d77182054845303fa59de92d783453079a048)) +* Do not simply divisions ([#3664](https://github.com/noir-lang/noir/issues/3664)) ([e5b981b](https://github.com/noir-lang/noir/commit/e5b981b08c2b345f00426acafe47b76d5262254d)) +* Docker builds ([#3620](https://github.com/noir-lang/noir/issues/3620)) ([f3eac52](https://github.com/noir-lang/noir/commit/f3eac5282860c1954ea2cee6a21633df5b1865fd)) +* **docs:** Update `editUrl` path for docusaurus ([#3184](https://github.com/noir-lang/noir/issues/3184)) ([4646a93](https://github.com/noir-lang/noir/commit/4646a93f5e95604b5710353764b2c4295efaef6b)) +* Download expected `bb` version if installed backend has version mismatch ([#3150](https://github.com/noir-lang/noir/issues/3150)) ([3f03435](https://github.com/noir-lang/noir/commit/3f03435552fe75b5c7a49bfc8d63d06573381220)) +* Error message for assigning the wrong type is backwards [#2804](https://github.com/noir-lang/noir/issues/2804) ([#2805](https://github.com/noir-lang/noir/issues/2805)) ([b2d62bf](https://github.com/noir-lang/noir/commit/b2d62bff3b7958b3ed62c285a7ebd45045ac2e05)) +* Finer bit size in bound constrain ([#2869](https://github.com/noir-lang/noir/issues/2869)) ([68385e2](https://github.com/noir-lang/noir/commit/68385e294a1501b19b28f3f5510e973283ed0821)) +* Fix aztec library after nargo fmt ([#3014](https://github.com/noir-lang/noir/issues/3014)) ([f43083c](https://github.com/noir-lang/noir/commit/f43083c744ff13aefa4d294a090c9445a9b70aac)) +* Fix crash when using undeclared traits ([#3509](https://github.com/noir-lang/noir/issues/3509)) ([8bb095a](https://github.com/noir-lang/noir/commit/8bb095af77d3b4043855841f1ae5799d75ed94f0)) +* Fix lexer error formatting ([#3274](https://github.com/noir-lang/noir/issues/3274)) ([74bd517](https://github.com/noir-lang/noir/commit/74bd517fe7839465ff086ffe622462bed5159006)) +* Fix method `program_counter`, change method signature ([#3012](https://github.com/noir-lang/noir/issues/3012)) ([5ea522b](https://github.com/noir-lang/noir/commit/5ea522b840ca0f6f90d02ca00f0de32f515d450f)) +* Fix panic in some cases when calling a private function ([#2799](https://github.com/noir-lang/noir/issues/2799)) ([078d5df](https://github.com/noir-lang/noir/commit/078d5df691d4ea48e83c9530cd40b64917eba0a7)) +* Fix panic when using repeated arrays which define variables ([#3221](https://github.com/noir-lang/noir/issues/3221)) ([c4faf3a](https://github.com/noir-lang/noir/commit/c4faf3a0a40eea1ee02e11dfe08b48c6b4438bbf)) +* Fix should_fail_with ([#2940](https://github.com/noir-lang/noir/issues/2940)) ([4f07b84](https://github.com/noir-lang/noir/commit/4f07b84458dba97530d8179a3b9b19101b472616)) +* Fix subtract with underflow in flattening pass ([#2796](https://github.com/noir-lang/noir/issues/2796)) ([f2ed505](https://github.com/noir-lang/noir/commit/f2ed5054b0b0335dd3ecb17369b0d2e6eafb1171)) +* Fixing versioning workflow ([#3296](https://github.com/noir-lang/noir/issues/3296)) ([3d5e43a](https://github.com/noir-lang/noir/commit/3d5e43a4b8cd9d2bb67d44a2eff93374c3603e42)) +* Flatten public inputs according to their index in numerial rather than ascii order ([#3605](https://github.com/noir-lang/noir/issues/3605)) ([a1f6343](https://github.com/noir-lang/noir/commit/a1f6343b7df1b166b1be4db09527694a3df2738a)) +* Follow dependencies when looking for a struct ([#3405](https://github.com/noir-lang/noir/issues/3405)) ([561b1b8](https://github.com/noir-lang/noir/commit/561b1b8f0b22d8b1800cb3552942a442a27c2a2c)) +* Force recompilation when `output_debug` flag is set. ([#2898](https://github.com/noir-lang/noir/issues/2898)) ([9854416](https://github.com/noir-lang/noir/commit/9854416f5ac03c9da6538edc6a0a540ccccb4b61)) +* **frontend:** Error on unsupported integer annotation ([#2778](https://github.com/noir-lang/noir/issues/2778)) ([90c3d8b](https://github.com/noir-lang/noir/commit/90c3d8baa3b7ae10bc99f6a767121f556ff75967)) +* Impl methods are no longer placed in contracts ([#3255](https://github.com/noir-lang/noir/issues/3255)) ([b673b07](https://github.com/noir-lang/noir/commit/b673b071663d9756d6346954fce7d4ec6e1577dd)) +* Improve error message when multiplying unit values ([#2950](https://github.com/noir-lang/noir/issues/2950)) ([57b7c55](https://github.com/noir-lang/noir/commit/57b7c55e7005876dc2e070c64e1b8115ca8a4242)) +* Include .nr and .sol files in builds ([#3039](https://github.com/noir-lang/noir/issues/3039)) ([ae8d0e9](https://github.com/noir-lang/noir/commit/ae8d0e9013f26b52e8f0bdc9f84866ffec50872d)) +* Issue an error when a module is declared twice & fix module search path ([#2801](https://github.com/noir-lang/noir/issues/2801)) ([7f76910](https://github.com/noir-lang/noir/commit/7f76910ebbd20e3d7a1db7541f2b7f43cd9b546d)) +* Lack of cjs package version ([#2848](https://github.com/noir-lang/noir/issues/2848)) ([adc2d59](https://github.com/noir-lang/noir/commit/adc2d597536b52c690dceb14ea5f8e30a493452c)) +* Make for loops a statement ([#2975](https://github.com/noir-lang/noir/issues/2975)) ([0e266eb](https://github.com/noir-lang/noir/commit/0e266ebc7328866b0b10554e37c9d9012a7b501c)) +* Match rust behaviour for left-shift overflow ([#3518](https://github.com/noir-lang/noir/issues/3518)) ([2d7ceb1](https://github.com/noir-lang/noir/commit/2d7ceb17edda1d9e70901cfd13f45cdc0df0d28d)) +* Minor problems with `aztec` publishing ([#3095](https://github.com/noir-lang/noir/issues/3095)) ([0fc8f20](https://github.com/noir-lang/noir/commit/0fc8f20b8b87d033d27ce18db039399c17f81837)) +* Move mimc to hash submodule ([#3361](https://github.com/noir-lang/noir/issues/3361)) ([3ec29f1](https://github.com/noir-lang/noir/commit/3ec29f17464703716978daacfa9f00c4f5013551)) +* Overflow checks for constant folding ([#3420](https://github.com/noir-lang/noir/issues/3420)) ([b7a6383](https://github.com/noir-lang/noir/commit/b7a6383cf9dc3bc4a71b9644352340c1e9339c81)) +* Parse parenthesized lvalues ([#3058](https://github.com/noir-lang/noir/issues/3058)) ([50ca58c](https://github.com/noir-lang/noir/commit/50ca58c7b133f8b21091dfd304379429284b0d60)) +* Prevent duplicated assert message transformation ([#3038](https://github.com/noir-lang/noir/issues/3038)) ([082a6d0](https://github.com/noir-lang/noir/commit/082a6d02dad67a25692bed15c340a16a848a320e)) +* Prevent mutating immutable bindings to mutable types ([#3075](https://github.com/noir-lang/noir/issues/3075)) ([d5ee20e](https://github.com/noir-lang/noir/commit/d5ee20ea43ccf1130f7d34231562f13e98ea636b)) +* **println:** Enable printing of arrays/strings >2 in fmt strings ([#2947](https://github.com/noir-lang/noir/issues/2947)) ([309fa70](https://github.com/noir-lang/noir/commit/309fa70823535c5340f986a17f4ddddcb8723bb8)) +* Recompile artefacts from a different noir version ([#3248](https://github.com/noir-lang/noir/issues/3248)) ([7347b27](https://github.com/noir-lang/noir/commit/7347b2742a5ad38d3d252e657810d061bab83e24)) +* Remove cast for field comparisons in brillig ([#2874](https://github.com/noir-lang/noir/issues/2874)) ([1fc1fdb](https://github.com/noir-lang/noir/commit/1fc1fdb4e15d2ce625ea79d458c5346fab418e49)) +* Remove duplication of code to load stdlib files ([#2868](https://github.com/noir-lang/noir/issues/2868)) ([b694aab](https://github.com/noir-lang/noir/commit/b694aab87c4665a3a89715c9d4096eeb3efb9944)) +* Remove quotes from println output ([#3574](https://github.com/noir-lang/noir/issues/3574)) ([127b6aa](https://github.com/noir-lang/noir/commit/127b6aa1ec8893275fdfa7795db7c52c4fc1d4dd)) +* Remove sha2_block test ([#3360](https://github.com/noir-lang/noir/issues/3360)) ([a48c03b](https://github.com/noir-lang/noir/commit/a48c03bec786d1fb85eef46eeddeccf29e81fe76)) +* Restrict fill_internal_slices pass to acir functions ([#3634](https://github.com/noir-lang/noir/issues/3634)) ([0cad9aa](https://github.com/noir-lang/noir/commit/0cad9aa9c19091b3679bdc6e7fe044194c5db7e0)) +* Return error rather than panicking on unreadable circuits ([#3179](https://github.com/noir-lang/noir/issues/3179)) ([d4f61d3](https://github.com/noir-lang/noir/commit/d4f61d3d51d515e40a5fd02d35315889f841bf53)) +* Show println output before an error occurs in `nargo execute` ([#3211](https://github.com/noir-lang/noir/issues/3211)) ([2f0b80d](https://github.com/noir-lang/noir/commit/2f0b80dda8401ce8962c857dbcd9548e7fdde4aa)) +* Silence unused variable warnings in stdlib ([#2795](https://github.com/noir-lang/noir/issues/2795)) ([5747bfe](https://github.com/noir-lang/noir/commit/5747bfed256f9179321ec0bd1e02f5f82723a4c7)) +* Somewhat reduce mem2reg memory usage ([#3572](https://github.com/noir-lang/noir/issues/3572)) ([9b9ed89](https://github.com/noir-lang/noir/commit/9b9ed890e68b6c7f0671b05919bdc86f593c5df5)) +* Split conditional_regression tests ([#2774](https://github.com/noir-lang/noir/issues/2774)) ([8ed8832](https://github.com/noir-lang/noir/commit/8ed8832c7b475cd28ae697a09f1ad07c539736db)) +* **ssa:** Do not replace previously constrained values ([#2647](https://github.com/noir-lang/noir/issues/2647)) ([d528844](https://github.com/noir-lang/noir/commit/d5288449a10d162a0340818a6beab54dd985a11a)) +* **traits:** Trait functions with a default implementation must not be followed by a semicolon ([#2987](https://github.com/noir-lang/noir/issues/2987)) ([a3593c0](https://github.com/noir-lang/noir/commit/a3593c042163d89bd012b7f901f3b18446209e82)) +* Transform hir before type checks ([#2994](https://github.com/noir-lang/noir/issues/2994)) ([a29b568](https://github.com/noir-lang/noir/commit/a29b568295e40e19dd354bbe47e31f922e08d8c9)) +* Update link to recursion example ([#3224](https://github.com/noir-lang/noir/issues/3224)) ([10eae15](https://github.com/noir-lang/noir/commit/10eae15c6992442876e184c7d2bd36a34f639ea1)) +* Use 128 bits for constant bit shift ([#3586](https://github.com/noir-lang/noir/issues/3586)) ([2ca9b05](https://github.com/noir-lang/noir/commit/2ca9b059317f0513ea21153ebdb468c4f6633de5)) +* Use pedersen_hash for merkle tree ([#3357](https://github.com/noir-lang/noir/issues/3357)) ([6b74d31](https://github.com/noir-lang/noir/commit/6b74d316fec3b379dd7b51064f1acb1a0e6a15cc)) +* Verify impls arising from function calls exist ([#3472](https://github.com/noir-lang/noir/issues/3472)) ([d7f919d](https://github.com/noir-lang/noir/commit/d7f919dcc001080ed24616ebbc37426ef7ac7638)) + + +### Miscellaneous Chores + +* `generateWitness` now returns a serialized witness file ([#2842](https://github.com/noir-lang/noir/issues/2842)) ([57d3f37](https://github.com/noir-lang/noir/commit/57d3f376d9ceadb75caf37a2bfc0e9394f76bfe6)) +* Bump MSRV to 1.71.1 ([#3353](https://github.com/noir-lang/noir/issues/3353)) ([78f2127](https://github.com/noir-lang/noir/commit/78f2127dd12e36e831e63fd670d9f9d870818af7)) +* Change stdlib function `pedersen` to `pedersen_commitment` ([#3341](https://github.com/noir-lang/noir/issues/3341)) ([964b777](https://github.com/noir-lang/noir/commit/964b7771506bdf8408d8917ab32bf51db8ce09d2)) +* Move circuit serialization circuit into acir ([#3345](https://github.com/noir-lang/noir/issues/3345)) ([122119b](https://github.com/noir-lang/noir/commit/122119b7377cec1b7c42c586c64b69b3bdf4d539)) +* **noir_js:** Rename inner and outer proof methods ([#2845](https://github.com/noir-lang/noir/issues/2845)) ([71dbbb8](https://github.com/noir-lang/noir/commit/71dbbb863a6f262da4804c17965ace627bf3a278)) +* Update to `bb` version 0.7.3 ([#2729](https://github.com/noir-lang/noir/issues/2729)) ([fce68d1](https://github.com/noir-lang/noir/commit/fce68d1404ae66bd7a71417d791dd70545bf24f2)) + +## [0.19.5](https://github.com/noir-lang/noir/compare/v0.19.4...v0.19.5) (2023-12-01) + + +### Features + +* Add `FieldElement::from<usize>` implementation ([#3647](https://github.com/noir-lang/noir/issues/3647)) ([8b7c5aa](https://github.com/noir-lang/noir/commit/8b7c5aa5311f4e6811438f67bd552b641b13fc9a)) +* Add package version to Nargo.toml metadata ([#3427](https://github.com/noir-lang/noir/issues/3427)) ([9e1717c](https://github.com/noir-lang/noir/commit/9e1717c2d96a0b9e394e5cb2fb9e1d09b5259ca0)) +* Add special case for boolean AND in acir-gen ([#3615](https://github.com/noir-lang/noir/issues/3615)) ([824039b](https://github.com/noir-lang/noir/commit/824039bcc0a3275f333ea94aecc701d129f99fe5)) +* Aztec-packages ([#3599](https://github.com/noir-lang/noir/issues/3599)) ([2cd6dc3](https://github.com/noir-lang/noir/commit/2cd6dc39e3a956aa5dff721d47aaf1921f98fded)) +* Aztec-packages ([#3626](https://github.com/noir-lang/noir/issues/3626)) ([e0a96ea](https://github.com/noir-lang/noir/commit/e0a96ea70b17c8c898dd72ac929f3969a4cec1d3)) +* Complex slice inputs for dynamic slice builtins ([#3617](https://github.com/noir-lang/noir/issues/3617)) ([8b23b34](https://github.com/noir-lang/noir/commit/8b23b349ae15afa48f6cbe8962586bbe79e79890)) +* Copy on write optimization for brillig ([#3522](https://github.com/noir-lang/noir/issues/3522)) ([da29c02](https://github.com/noir-lang/noir/commit/da29c02327acb2f46f5a7a25c7404dfa44c82616)) +* Data bus ([#3508](https://github.com/noir-lang/noir/issues/3508)) ([6b0bdbc](https://github.com/noir-lang/noir/commit/6b0bdbced1bfe2c92e90dd7b70ca8f9e5ccb7c0d)) +* Implement integer printing ([#3577](https://github.com/noir-lang/noir/issues/3577)) ([6601408](https://github.com/noir-lang/noir/commit/6601408e378b2afe4fdfd8e04482c39311ccc7e9)) +* Implement raw string literals ([#3556](https://github.com/noir-lang/noir/issues/3556)) ([87a302f](https://github.com/noir-lang/noir/commit/87a302fbc26d5fd42694953935d95a7ccb3d50a0)) +* **lsp:** Add goto definition for functions ([#3656](https://github.com/noir-lang/noir/issues/3656)) ([7bb7356](https://github.com/noir-lang/noir/commit/7bb735662c86e6533ac58f448ad748e34f02edb7)) +* Reuse witnesses more when interacting with memory ([#3658](https://github.com/noir-lang/noir/issues/3658)) ([5a4a73d](https://github.com/noir-lang/noir/commit/5a4a73d24ddd7d2bb46c85714397ee6e031c97a6)) + + +### Bug Fixes + +* Corrected the formatting of error message parameters in index out of bounds error ([#3630](https://github.com/noir-lang/noir/issues/3630)) ([3bba386](https://github.com/noir-lang/noir/commit/3bba3862dc8703410681300be894bfd1ebca7336)) +* Do not simply divisions ([#3664](https://github.com/noir-lang/noir/issues/3664)) ([e5b981b](https://github.com/noir-lang/noir/commit/e5b981b08c2b345f00426acafe47b76d5262254d)) +* Docker builds ([#3620](https://github.com/noir-lang/noir/issues/3620)) ([f3eac52](https://github.com/noir-lang/noir/commit/f3eac5282860c1954ea2cee6a21633df5b1865fd)) +* Flatten public inputs according to their index in numerial rather than ascii order ([#3605](https://github.com/noir-lang/noir/issues/3605)) ([a1f6343](https://github.com/noir-lang/noir/commit/a1f6343b7df1b166b1be4db09527694a3df2738a)) +* Restrict fill_internal_slices pass to acir functions ([#3634](https://github.com/noir-lang/noir/issues/3634)) ([0cad9aa](https://github.com/noir-lang/noir/commit/0cad9aa9c19091b3679bdc6e7fe044194c5db7e0)) + +## [0.19.4](https://github.com/noir-lang/noir/compare/v0.19.3...v0.19.4) (2023-11-28) + + +### Features + +* Add --check option to nargo fmt for dry-run formatting verification ([#3530](https://github.com/noir-lang/noir/issues/3530)) ([4469707](https://github.com/noir-lang/noir/commit/4469707d97085fab0f7ade8d015dc827c56156ee)) +* Add support for tuple values in `noir_codegen` ([#3592](https://github.com/noir-lang/noir/issues/3592)) ([346d75f](https://github.com/noir-lang/noir/commit/346d75f9dd9261996d4d7bb80eb7e4118e8f8ce2)) +* Codegen typed interfaces for functions in `noir_codegen` ([#3533](https://github.com/noir-lang/noir/issues/3533)) ([290c463](https://github.com/noir-lang/noir/commit/290c463622a93a34293f73b5bf2aea7ade30a11c)) +* Export `CompiledCircuit` from codegened TS ([#3589](https://github.com/noir-lang/noir/issues/3589)) ([e06c675](https://github.com/noir-lang/noir/commit/e06c67500da11518caffe0e98bdb9cd7f5f89049)) +* Remove type arrays for flat slices ([#3466](https://github.com/noir-lang/noir/issues/3466)) ([8225b2b](https://github.com/noir-lang/noir/commit/8225b2b379ddf145f9418f8517478704f9aac350)) +* Send and receive unflattened public inputs to backend ([#3543](https://github.com/noir-lang/noir/issues/3543)) ([a7bdc67](https://github.com/noir-lang/noir/commit/a7bdc67ef3ec2037bffc4f1f472907cad786c319)) + + +### Bug Fixes + +* Compiler version error message ([#3558](https://github.com/noir-lang/noir/issues/3558)) ([026a358](https://github.com/noir-lang/noir/commit/026a3587b01ddc8f444ff588a7b3f3fd1a0bb386)) +* Remove quotes from println output ([#3574](https://github.com/noir-lang/noir/issues/3574)) ([127b6aa](https://github.com/noir-lang/noir/commit/127b6aa1ec8893275fdfa7795db7c52c4fc1d4dd)) +* Somewhat reduce mem2reg memory usage ([#3572](https://github.com/noir-lang/noir/issues/3572)) ([9b9ed89](https://github.com/noir-lang/noir/commit/9b9ed890e68b6c7f0671b05919bdc86f593c5df5)) +* Use 128 bits for constant bit shift ([#3586](https://github.com/noir-lang/noir/issues/3586)) ([2ca9b05](https://github.com/noir-lang/noir/commit/2ca9b059317f0513ea21153ebdb468c4f6633de5)) + +## [0.19.3](https://github.com/noir-lang/noir/compare/v0.19.2...v0.19.3) (2023-11-22) + + +### Features + +* Add debugger commands to introspect (and modify) the current state ([#3391](https://github.com/noir-lang/noir/issues/3391)) ([9e1ad85](https://github.com/noir-lang/noir/commit/9e1ad858cf8a1d9aba0137abe6a749267498bfaf)) +* Add LSP command to profile opcodes in vscode ([#3496](https://github.com/noir-lang/noir/issues/3496)) ([6fbf77a](https://github.com/noir-lang/noir/commit/6fbf77ae2b87a55db92344f5066a82ccaf6c2086)) +* Add lsp formatting ([#3433](https://github.com/noir-lang/noir/issues/3433)) ([286c876](https://github.com/noir-lang/noir/commit/286c87694fda185f25b05cec5504142643bc207f)) +* Allow providing custom foreign call executors to `execute_circuit` ([#3506](https://github.com/noir-lang/noir/issues/3506)) ([d27db33](https://github.com/noir-lang/noir/commit/d27db332f8c320ffd9b5520bebbd83ae09e31de7)) +* Compile without a backend ([#3437](https://github.com/noir-lang/noir/issues/3437)) ([d69cf5d](https://github.com/noir-lang/noir/commit/d69cf5debcc430bb019b6cc95774aac084776dda)) +* Enable the `fmt` command in the help menu ([#3328](https://github.com/noir-lang/noir/issues/3328)) ([63d414c](https://github.com/noir-lang/noir/commit/63d414c06a399525601e3db11dc48b180e93c2d8)) +* Handle constant index operations on simple slices ([#3464](https://github.com/noir-lang/noir/issues/3464)) ([7ae12f8](https://github.com/noir-lang/noir/commit/7ae12f8c5243d31b2f410c246ed6b9e2fcea5d4c)) + + +### Bug Fixes + +* "Missing trait impl" error in trait dispatch ([#3440](https://github.com/noir-lang/noir/issues/3440)) ([52daaec](https://github.com/noir-lang/noir/commit/52daaec504101fe3c0caa30441c17f30a34af475)) +* Adding proving key initialization ([#3322](https://github.com/noir-lang/noir/issues/3322)) ([3383740](https://github.com/noir-lang/noir/commit/3383740f9a0004f2ee77c9686f81baed6cd1917c)) +* Allow `where` clause on all functions and improve error message ([#3465](https://github.com/noir-lang/noir/issues/3465)) ([1647e33](https://github.com/noir-lang/noir/commit/1647e33564bf56ab8721a365f5fc6bcb38901412)) +* Apply predicate to over/underflow checks ([#3494](https://github.com/noir-lang/noir/issues/3494)) ([fc3edf7](https://github.com/noir-lang/noir/commit/fc3edf7aa5da9074614fa900bbcb57e512e3d56b)) +* **debugger:** Step through foreign calls and breakpoints inside Brillig blocks ([#3511](https://github.com/noir-lang/noir/issues/3511)) ([5d77d7a](https://github.com/noir-lang/noir/commit/5d77d7ac82a4df6995ca151b2c8070044cb1fe9d)) +* Fix crash when using undeclared traits ([#3509](https://github.com/noir-lang/noir/issues/3509)) ([8bb095a](https://github.com/noir-lang/noir/commit/8bb095af77d3b4043855841f1ae5799d75ed94f0)) +* Match rust behaviour for left-shift overflow ([#3518](https://github.com/noir-lang/noir/issues/3518)) ([2d7ceb1](https://github.com/noir-lang/noir/commit/2d7ceb17edda1d9e70901cfd13f45cdc0df0d28d)) +* Verify impls arising from function calls exist ([#3472](https://github.com/noir-lang/noir/issues/3472)) ([d7f919d](https://github.com/noir-lang/noir/commit/d7f919dcc001080ed24616ebbc37426ef7ac7638)) + ## [0.19.2](https://github.com/noir-lang/noir/compare/v0.19.1...v0.19.2) (2023-11-07) diff --git a/Cargo.lock b/Cargo.lock index 52c735a0b5..ff6fda839d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "acir" -version = "0.33.0" +version = "0.37.0" dependencies = [ "acir_field", "base64", @@ -23,7 +23,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.33.0" +version = "0.37.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -37,7 +37,7 @@ dependencies = [ [[package]] name = "acvm" -version = "0.33.0" +version = "0.37.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -54,7 +54,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.33.0" +version = "0.37.0" dependencies = [ "acir", "blake2", @@ -68,7 +68,7 @@ dependencies = [ [[package]] name = "acvm_js" -version = "0.33.0" +version = "0.37.0" dependencies = [ "acvm", "barretenberg_blackbox_solver", @@ -89,7 +89,7 @@ dependencies = [ [[package]] name = "acvm_stdlib" -version = "0.33.0" +version = "0.37.0" dependencies = [ "acir", ] @@ -218,7 +218,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arena" -version = "0.19.2" +version = "0.20.0" dependencies = [ "generational-arena", ] @@ -414,12 +414,31 @@ dependencies = [ "waitpid-any", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "aztec_macros" +version = "0.20.0" +dependencies = [ + "iter-extended", + "noirc_frontend", +] + [[package]] name = "backend-interface" version = "0.11.0" @@ -430,6 +449,7 @@ dependencies = [ "const_format", "dirs", "flate2", + "log", "reqwest", "serde", "serde_json", @@ -456,7 +476,7 @@ dependencies = [ [[package]] name = "barretenberg_blackbox_solver" -version = "0.33.0" +version = "0.37.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -593,7 +613,7 @@ dependencies = [ [[package]] name = "brillig" -version = "0.33.0" +version = "0.37.0" dependencies = [ "acir_field", "serde", @@ -601,7 +621,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.33.0" +version = "0.37.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -1141,6 +1161,16 @@ dependencies = [ "itertools", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.3" @@ -1499,6 +1529,19 @@ dependencies = [ "syn 2.0.26", ] +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1622,11 +1665,10 @@ dependencies = [ [[package]] name = "fm" -version = "0.19.2" +version = "0.20.0" dependencies = [ "codespan-reporting", "iter-extended", - "rust-embed", "serde", "tempfile", ] @@ -1925,6 +1967,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.2" @@ -1980,6 +2031,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.27" @@ -2177,14 +2234,14 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.2", "rustix", "windows-sys 0.48.0", ] [[package]] name = "iter-extended" -version = "0.19.2" +version = "0.20.0" [[package]] name = "itertools" @@ -2406,7 +2463,7 @@ checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] name = "nargo" -version = "0.19.2" +version = "0.20.0" dependencies = [ "acvm", "codespan-reporting", @@ -2421,12 +2478,13 @@ dependencies = [ "rayon", "rustc_version", "serde", + "tempfile", "thiserror", ] [[package]] name = "nargo_cli" -version = "0.19.2" +version = "0.20.0" dependencies = [ "acvm", "assert_cmd", @@ -2441,6 +2499,7 @@ dependencies = [ "const_format", "criterion", "dirs", + "env_logger", "fm", "hex", "iai", @@ -2462,6 +2521,7 @@ dependencies = [ "rustc_version", "serde", "serde_json", + "similar-asserts", "tempfile", "termcolor", "test-binary", @@ -2470,11 +2530,14 @@ dependencies = [ "tokio-util", "toml", "tower", + "tracing", + "tracing-appender", + "tracing-subscriber", ] [[package]] name = "nargo_fmt" -version = "0.19.2" +version = "0.20.0" dependencies = [ "bytecount", "noirc_frontend", @@ -2486,7 +2549,7 @@ dependencies = [ [[package]] name = "nargo_toml" -version = "0.19.2" +version = "0.20.0" dependencies = [ "dirs", "fm", @@ -2535,7 +2598,7 @@ dependencies = [ [[package]] name = "noir_debugger" -version = "0.19.2" +version = "0.20.0" dependencies = [ "acvm", "codespan-reporting", @@ -2549,16 +2612,15 @@ dependencies = [ [[package]] name = "noir_lsp" -version = "0.19.2" +version = "0.20.0" dependencies = [ "acvm", "async-lsp", - "cfg-if", "codespan-lsp", - "codespan-reporting", "fm", "lsp-types 0.94.1", "nargo", + "nargo_fmt", "nargo_toml", "noirc_driver", "noirc_errors", @@ -2573,11 +2635,10 @@ dependencies = [ [[package]] name = "noir_wasm" -version = "0.19.2" +version = "0.20.0" dependencies = [ "acvm", "build-data", - "cfg-if", "console_error_panic_hook", "fm", "getrandom", @@ -2595,7 +2656,7 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "0.19.2" +version = "0.20.0" dependencies = [ "acvm", "iter-extended", @@ -2612,7 +2673,7 @@ dependencies = [ [[package]] name = "noirc_abi_wasm" -version = "0.19.2" +version = "0.20.0" dependencies = [ "acvm", "build-data", @@ -2629,9 +2690,10 @@ dependencies = [ [[package]] name = "noirc_driver" -version = "0.19.2" +version = "0.20.0" dependencies = [ "acvm", + "aztec_macros", "build-data", "clap", "fm", @@ -2641,12 +2703,13 @@ dependencies = [ "noirc_errors", "noirc_evaluator", "noirc_frontend", + "rust-embed", "serde", ] [[package]] name = "noirc_errors" -version = "0.19.2" +version = "0.20.0" dependencies = [ "acvm", "chumsky", @@ -2659,7 +2722,7 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "0.19.2" +version = "0.20.0" dependencies = [ "acvm", "fxhash", @@ -2674,7 +2737,7 @@ dependencies = [ [[package]] name = "noirc_frontend" -version = "0.19.2" +version = "0.20.0" dependencies = [ "acvm", "arena", @@ -2696,7 +2759,7 @@ dependencies = [ [[package]] name = "noirc_printable_type" -version = "0.19.2" +version = "0.20.0" dependencies = [ "acvm", "iter-extended", @@ -2712,6 +2775,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-bigint" version = "0.4.3" @@ -2759,7 +2832,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.2", "libc", ] @@ -2784,6 +2857,12 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "owo-colors" version = "3.5.0" @@ -4383,22 +4462,33 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "log", "pin-project-lite", "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-appender" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" +dependencies = [ + "crossbeam-channel", + "thiserror", + "time", + "tracing-subscriber", +] + [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", @@ -4407,9 +4497,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -4425,15 +4515,29 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ + "nu-ansi-term", "sharded-slab", + "smallvec", "thread_local", "tracing-core", + "tracing-log", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index bc2c4e9f73..7cd00ee0a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ + "aztec_macros", "compiler/noirc_evaluator", "compiler/noirc_frontend", "compiler/noirc_errors", @@ -38,7 +39,7 @@ resolver = "2" [workspace.package] # x-release-please-start-version -version = "0.19.2" +version = "0.20.0" # x-release-please-end authors = ["The Noir Team "] edition = "2021" @@ -49,14 +50,14 @@ repository = "https://github.com/noir-lang/noir/" [workspace.dependencies] # ACVM workspace dependencies -acir = { path = "acvm-repo/acir", default-features = false } -acvm = { path = "acvm-repo/acvm" } -acir_field = { path = "acvm-repo/acir_field", default-features = false } -stdlib = { package = "acvm_stdlib", path = "acvm-repo/stdlib", default-features = false } -brillig = { path = "acvm-repo/brillig", default-features = false } -brillig_vm = { path = "acvm-repo/brillig_vm", default-features = false } -acvm_blackbox_solver = { path = "acvm-repo/blackbox_solver", default-features = false } -barretenberg_blackbox_solver = { path = "acvm-repo/barretenberg_blackbox_solver", default-features = false } +acir_field = { version = "0.37.0", path = "acvm-repo/acir_field", default-features = false } +acir = { version = "0.37.0", path = "acvm-repo/acir", default-features = false } +acvm = { version = "0.37.0", path = "acvm-repo/acvm" } +stdlib = { version = "0.37.0", package = "acvm_stdlib", path = "acvm-repo/stdlib", default-features = false } +brillig = { version = "0.37.0", path = "acvm-repo/brillig", default-features = false } +brillig_vm = { version = "0.37.0", path = "acvm-repo/brillig_vm", default-features = false } +acvm_blackbox_solver = { version = "0.37.0", path = "acvm-repo/blackbox_solver", default-features = false } +barretenberg_blackbox_solver = { version = "0.37.0", path = "acvm-repo/barretenberg_blackbox_solver", default-features = false } # Noir compiler workspace dependencies arena = { path = "compiler/utils/arena" } @@ -95,7 +96,7 @@ getrandom = "0.2" cfg-if = "1.0.0" -clap = { version = "4.3.19", features = ["derive"] } +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" @@ -118,8 +119,25 @@ hex = "0.4.2" const_format = "0.2.30" num-bigint = "0.4" num-traits = "0.2" +similar-asserts = "1.5.0" +log = "0.4.17" + +tracing = "0.1.40" [profile.dev] # This is required to be able to run `cargo test` in acvm_js due to the `locals exceeds maximum` error. # See https://ritik-mishra.medium.com/resolving-the-wasm-pack-error-locals-exceed-maximum-ec3a9d96685b opt-level = 1 + + +[profile.size] +inherits = "release" +lto = true +opt-level = "z" + +[profile.size-aggressive] +inherits = "release" +strip = true +lto = true +panic = "abort" +opt-level = "z" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..ac818cb8bd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM rust:alpine3.17 +RUN apk update \ + && apk upgrade \ + && apk add --no-cache \ + build-base \ + bash +WORKDIR /usr/src/noir +COPY . . +RUN ./scripts/bootstrap_native.sh + +# When running the container, mount the current working directory to /project. +FROM alpine:3.17 +COPY --from=0 /usr/src/noir/target/release/nargo /usr/src/noir/target/release/nargo +WORKDIR /project +ENTRYPOINT ["/usr/src/noir/target/release/nargo"] \ No newline at end of file diff --git a/Dockerfile.ci b/Dockerfile.ci new file mode 100644 index 0000000000..9ca995fd94 --- /dev/null +++ b/Dockerfile.ci @@ -0,0 +1,40 @@ +FROM rust:1-slim-bookworm as test-base +RUN apt-get update && apt-get upgrade -y && apt-get install build-essential git -y +WORKDIR /usr/src/noir +COPY . . +RUN ./scripts/bootstrap_native.sh +ENV PATH="${PATH}:/usr/src/noir/target/release/" + +FROM test-base as test-cargo +RUN apt-get install -y curl libc++-dev +RUN ./scripts/test_native.sh + +FROM test-base as test-js +RUN apt-get install pkg-config libssl-dev -y +RUN ./scripts/install_wasm-bindgen.sh +RUN apt-get install -y ca-certificates curl gnupg +RUN mkdir -p /etc/apt/keyrings +RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg +RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list +RUN apt-get update && apt-get install nodejs -y +RUN corepack enable +RUN yarn --immutable +RUN apt-get install -y jq +RUN yarn build +RUN yarn workspace @noir-lang/acvm_js test +RUN npx playwright install && npx playwright install-deps +RUN yarn workspace @noir-lang/acvm_js test:browser +RUN yarn workspace @noir-lang/noirc_abi test +RUN yarn workspace @noir-lang/noirc_abi test:browser +RUN yarn workspace @noir-lang/backend_barretenberg test +RUN ./scripts/nargo_compile_noir_js_assert_lt.sh +RUN rm -rf /usr/src/noir/tooling/noir_js/test/noir_compiled_examples/assert_lt/target/debug_assert_lt.json +RUN yarn workspace @noir-lang/noir_js test +RUN ./scripts/nargo_compile_wasm_fixtures.sh +RUN yarn workspace @noir-lang/noir_wasm test:node +RUN yarn workspace @noir-lang/noir_wasm test:browser +RUN ./scripts/nargo_compile_noir_codegen_assert_lt.sh +RUN rm -rf /usr/src/noir/tooling/noir_codegen/test/assert_lt/target/debug_assert_lt.json +RUN yarn workspace @noir-lang/noir_codegen test +RUN apt-get install -y libc++-dev +RUN yarn test:integration diff --git a/Dockerfile.packages b/Dockerfile.packages new file mode 100644 index 0000000000..17eb0bcd64 --- /dev/null +++ b/Dockerfile.packages @@ -0,0 +1,21 @@ +FROM rust:alpine3.17 +RUN apk update \ + && apk upgrade \ + && apk add --no-cache \ + build-base \ + pkgconfig \ + openssl-dev \ + npm \ + yarn \ + bash \ + jq \ + git + +WORKDIR /usr/src/noir +COPY . . +RUN ./scripts/bootstrap_packages.sh + +FROM scratch +COPY --from=0 /usr/src/noir/packages /usr/src/noir/packages +# For some unknown reason, on alpine only, we need this to exist. +COPY --from=0 /usr/src/noir/node_modules/@noir-lang /usr/src/noir/node_modules/@noir-lang \ No newline at end of file diff --git a/README.md b/README.md index c48c911018..2fc47f16fe 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ This crate's minimum supported rustc version is 1.71.1. ## Working on this project -This project uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. Please follow [our guidelines](https://noir-lang.org/getting_started/nargo_installation/#option-4-compile-from-source) to setup your environment for working on the project. +This project uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. Please follow [our guidelines](https://noir-lang.org/getting_started/nargo_installation/#option-3-compile-from-source) to setup your environment for working on the project. ### Building against a different local/remote version of Barretenberg diff --git a/acvm-repo/CHANGELOG.md b/acvm-repo/CHANGELOG.md index 3eb4e9146c..fea0029744 100644 --- a/acvm-repo/CHANGELOG.md +++ b/acvm-repo/CHANGELOG.md @@ -5,6 +5,202 @@ 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.37.0](https://github.com/noir-lang/noir/compare/v0.36.0...v0.37.0) (2023-12-01) + + +### ⚠ BREAKING CHANGES + +* Move circuit serialization circuit into acir ([#3345](https://github.com/noir-lang/noir/issues/3345)) +* expose pedersen hash in acir and bb solver ([#3269](https://github.com/noir-lang/noir/issues/3269)) +* Switch to new pedersen implementation ([#3151](https://github.com/noir-lang/noir/issues/3151)) +* Pass ACIR to ACVM by reference rather than passing ownership ([#2872](https://github.com/noir-lang/noir/issues/2872)) +* **wasm:** improve and simplify wasm compiler interface ([#2976](https://github.com/noir-lang/noir/issues/2976)) +* Maintain shape of foreign call arguments ([#2935](https://github.com/noir-lang/noir/issues/2935)) + +### Features + +* **acvm_js:** Export black box solver functions ([#2812](https://github.com/noir-lang/noir/issues/2812)) ([da8a98e](https://github.com/noir-lang/noir/commit/da8a98ed312fe69cb0bdb8f9d0a70ee7a981398f)) +* **acvm:** Separate ACVM optimizations and transformations ([#2979](https://github.com/noir-lang/noir/issues/2979)) ([5865d1a](https://github.com/noir-lang/noir/commit/5865d1a1bca16e1853663c71f893ff81fa3f7185)) +* Add `FieldElement::from<usize>` implementation ([#3647](https://github.com/noir-lang/noir/issues/3647)) ([8b7c5aa](https://github.com/noir-lang/noir/commit/8b7c5aa5311f4e6811438f67bd552b641b13fc9a)) +* Add ACIR serializer C++ codegen ([#2961](https://github.com/noir-lang/noir/issues/2961)) ([7556982](https://github.com/noir-lang/noir/commit/7556982dbebe25eaa17240abbe270b771b55de45)) +* Add conditional compilation of methods based on the underlying field being used ([#3045](https://github.com/noir-lang/noir/issues/3045)) ([2e008e2](https://github.com/noir-lang/noir/commit/2e008e2438795bbc41b0641e830378b76bf2e194)) +* Add debugger commands to introspect (and modify) the current state ([#3391](https://github.com/noir-lang/noir/issues/3391)) ([9e1ad85](https://github.com/noir-lang/noir/commit/9e1ad858cf8a1d9aba0137abe6a749267498bfaf)) +* Aztec-packages ([#3599](https://github.com/noir-lang/noir/issues/3599)) ([2cd6dc3](https://github.com/noir-lang/noir/commit/2cd6dc39e3a956aa5dff721d47aaf1921f98fded)) +* Expose pedersen hash in acir and bb solver ([#3269](https://github.com/noir-lang/noir/issues/3269)) ([0108b6c](https://github.com/noir-lang/noir/commit/0108b6c1e8dc0dfc766ab3c4944deae9354dec36)) +* Extract Brillig VM to allow step debugging ([#3259](https://github.com/noir-lang/noir/issues/3259)) ([f6431f9](https://github.com/noir-lang/noir/commit/f6431f99711f15a96a4f7fed2f413daece94b5e1)) +* Implement euclidean division and signed division in terms of `AcirVar`s ([#3230](https://github.com/noir-lang/noir/issues/3230)) ([b8b7782](https://github.com/noir-lang/noir/commit/b8b77825410c0e1f95549259a51e2c40de1ec342)) +* Maintain shape of foreign call arguments ([#2935](https://github.com/noir-lang/noir/issues/2935)) ([f7869e6](https://github.com/noir-lang/noir/commit/f7869e6fb492b617e776e538ac4babfa56261d26)) +* Pass ACIR to ACVM by reference rather than passing ownership ([#2872](https://github.com/noir-lang/noir/issues/2872)) ([b3a9c34](https://github.com/noir-lang/noir/commit/b3a9c343993ce3207de62106bda6cb2b2ef3de50)) +* Pass brillig bytecode to VM by reference ([#3030](https://github.com/noir-lang/noir/issues/3030)) ([4ee290b](https://github.com/noir-lang/noir/commit/4ee290b8b6f75bc1974a5750248570eeca8d244e)) +* Refactor debugger and separate core from UI ([#3308](https://github.com/noir-lang/noir/issues/3308)) ([8466810](https://github.com/noir-lang/noir/commit/846681079ab7295b201480a5c8baebc45e858c6f)) +* Replace boolean range constraints with arithmetic opcodes ([#3234](https://github.com/noir-lang/noir/issues/3234)) ([949222c](https://github.com/noir-lang/noir/commit/949222c20d9e65152e3814d02da1c4c41ffc23a5)) +* Save Brillig execution state in ACVM ([#3026](https://github.com/noir-lang/noir/issues/3026)) ([88682da](https://github.com/noir-lang/noir/commit/88682da87ffc9e26da5c9e4b5a4d8e62a6ee43c6)) +* Solve `fixed_base_scalar_mul` black box functions in rust ([#3153](https://github.com/noir-lang/noir/issues/3153)) ([1c1afbc](https://github.com/noir-lang/noir/commit/1c1afbcddf0b5fdb39f00ad28ae90caf699d1265)) +* Switch to new pedersen implementation ([#3151](https://github.com/noir-lang/noir/issues/3151)) ([35fb3f7](https://github.com/noir-lang/noir/commit/35fb3f7076d52db7ca3bef0a70a3dbccaf82f58d)) +* **wasm:** Improve and simplify wasm compiler interface ([#2976](https://github.com/noir-lang/noir/issues/2976)) ([1b5124b](https://github.com/noir-lang/noir/commit/1b5124bc74f7ac5360db04b34d1b7b2284061fd3)) + + +### Bug Fixes + +* ACIR optimizer should update assertion messages ([#3010](https://github.com/noir-lang/noir/issues/3010)) ([758b6b6](https://github.com/noir-lang/noir/commit/758b6b62918907c1a39f3090a77419003551745e)) +* **acvm:** Return false rather than panicking on invalid ECDSA signatures ([#2783](https://github.com/noir-lang/noir/issues/2783)) ([155abc0](https://github.com/noir-lang/noir/commit/155abc0d99fff41c79163c16bf297d41e5dff0fa)) +* Determinism of fallback transformer ([#3100](https://github.com/noir-lang/noir/issues/3100)) ([12daad1](https://github.com/noir-lang/noir/commit/12daad19c902caf5ee9e2eb4b6847bde5a924353)) +* Fix method `program_counter`, change method signature ([#3012](https://github.com/noir-lang/noir/issues/3012)) ([5ea522b](https://github.com/noir-lang/noir/commit/5ea522b840ca0f6f90d02ca00f0de32f515d450f)) +* Minor problems with `aztec` publishing ([#3095](https://github.com/noir-lang/noir/issues/3095)) ([0fc8f20](https://github.com/noir-lang/noir/commit/0fc8f20b8b87d033d27ce18db039399c17f81837)) +* Prevent duplicated assert message transformation ([#3038](https://github.com/noir-lang/noir/issues/3038)) ([082a6d0](https://github.com/noir-lang/noir/commit/082a6d02dad67a25692bed15c340a16a848a320e)) +* Return error rather than panicking on unreadable circuits ([#3179](https://github.com/noir-lang/noir/issues/3179)) ([d4f61d3](https://github.com/noir-lang/noir/commit/d4f61d3d51d515e40a5fd02d35315889f841bf53)) + + +### Miscellaneous Chores + +* Move circuit serialization circuit into acir ([#3345](https://github.com/noir-lang/noir/issues/3345)) ([122119b](https://github.com/noir-lang/noir/commit/122119b7377cec1b7c42c586c64b69b3bdf4d539)) + +## [0.36.0](https://github.com/noir-lang/noir/compare/v0.35.0...v0.36.0) (2023-12-01) + + +### ⚠ BREAKING CHANGES + +* Move circuit serialization circuit into acir ([#3345](https://github.com/noir-lang/noir/issues/3345)) +* expose pedersen hash in acir and bb solver ([#3269](https://github.com/noir-lang/noir/issues/3269)) +* Switch to new pedersen implementation ([#3151](https://github.com/noir-lang/noir/issues/3151)) +* Pass ACIR to ACVM by reference rather than passing ownership ([#2872](https://github.com/noir-lang/noir/issues/2872)) +* **wasm:** improve and simplify wasm compiler interface ([#2976](https://github.com/noir-lang/noir/issues/2976)) +* Maintain shape of foreign call arguments ([#2935](https://github.com/noir-lang/noir/issues/2935)) + +### Features + +* **acvm_js:** Export black box solver functions ([#2812](https://github.com/noir-lang/noir/issues/2812)) ([da8a98e](https://github.com/noir-lang/noir/commit/da8a98ed312fe69cb0bdb8f9d0a70ee7a981398f)) +* **acvm:** Separate ACVM optimizations and transformations ([#2979](https://github.com/noir-lang/noir/issues/2979)) ([5865d1a](https://github.com/noir-lang/noir/commit/5865d1a1bca16e1853663c71f893ff81fa3f7185)) +* Add `FieldElement::from<usize>` implementation ([#3647](https://github.com/noir-lang/noir/issues/3647)) ([8b7c5aa](https://github.com/noir-lang/noir/commit/8b7c5aa5311f4e6811438f67bd552b641b13fc9a)) +* Add ACIR serializer C++ codegen ([#2961](https://github.com/noir-lang/noir/issues/2961)) ([7556982](https://github.com/noir-lang/noir/commit/7556982dbebe25eaa17240abbe270b771b55de45)) +* Add conditional compilation of methods based on the underlying field being used ([#3045](https://github.com/noir-lang/noir/issues/3045)) ([2e008e2](https://github.com/noir-lang/noir/commit/2e008e2438795bbc41b0641e830378b76bf2e194)) +* Add debugger commands to introspect (and modify) the current state ([#3391](https://github.com/noir-lang/noir/issues/3391)) ([9e1ad85](https://github.com/noir-lang/noir/commit/9e1ad858cf8a1d9aba0137abe6a749267498bfaf)) +* Aztec-packages ([#3599](https://github.com/noir-lang/noir/issues/3599)) ([2cd6dc3](https://github.com/noir-lang/noir/commit/2cd6dc39e3a956aa5dff721d47aaf1921f98fded)) +* Expose pedersen hash in acir and bb solver ([#3269](https://github.com/noir-lang/noir/issues/3269)) ([0108b6c](https://github.com/noir-lang/noir/commit/0108b6c1e8dc0dfc766ab3c4944deae9354dec36)) +* Extract Brillig VM to allow step debugging ([#3259](https://github.com/noir-lang/noir/issues/3259)) ([f6431f9](https://github.com/noir-lang/noir/commit/f6431f99711f15a96a4f7fed2f413daece94b5e1)) +* Implement euclidean division and signed division in terms of `AcirVar`s ([#3230](https://github.com/noir-lang/noir/issues/3230)) ([b8b7782](https://github.com/noir-lang/noir/commit/b8b77825410c0e1f95549259a51e2c40de1ec342)) +* Maintain shape of foreign call arguments ([#2935](https://github.com/noir-lang/noir/issues/2935)) ([f7869e6](https://github.com/noir-lang/noir/commit/f7869e6fb492b617e776e538ac4babfa56261d26)) +* Pass ACIR to ACVM by reference rather than passing ownership ([#2872](https://github.com/noir-lang/noir/issues/2872)) ([b3a9c34](https://github.com/noir-lang/noir/commit/b3a9c343993ce3207de62106bda6cb2b2ef3de50)) +* Pass brillig bytecode to VM by reference ([#3030](https://github.com/noir-lang/noir/issues/3030)) ([4ee290b](https://github.com/noir-lang/noir/commit/4ee290b8b6f75bc1974a5750248570eeca8d244e)) +* Refactor debugger and separate core from UI ([#3308](https://github.com/noir-lang/noir/issues/3308)) ([8466810](https://github.com/noir-lang/noir/commit/846681079ab7295b201480a5c8baebc45e858c6f)) +* Replace boolean range constraints with arithmetic opcodes ([#3234](https://github.com/noir-lang/noir/issues/3234)) ([949222c](https://github.com/noir-lang/noir/commit/949222c20d9e65152e3814d02da1c4c41ffc23a5)) +* Save Brillig execution state in ACVM ([#3026](https://github.com/noir-lang/noir/issues/3026)) ([88682da](https://github.com/noir-lang/noir/commit/88682da87ffc9e26da5c9e4b5a4d8e62a6ee43c6)) +* Solve `fixed_base_scalar_mul` black box functions in rust ([#3153](https://github.com/noir-lang/noir/issues/3153)) ([1c1afbc](https://github.com/noir-lang/noir/commit/1c1afbcddf0b5fdb39f00ad28ae90caf699d1265)) +* Switch to new pedersen implementation ([#3151](https://github.com/noir-lang/noir/issues/3151)) ([35fb3f7](https://github.com/noir-lang/noir/commit/35fb3f7076d52db7ca3bef0a70a3dbccaf82f58d)) +* **wasm:** Improve and simplify wasm compiler interface ([#2976](https://github.com/noir-lang/noir/issues/2976)) ([1b5124b](https://github.com/noir-lang/noir/commit/1b5124bc74f7ac5360db04b34d1b7b2284061fd3)) + + +### Bug Fixes + +* ACIR optimizer should update assertion messages ([#3010](https://github.com/noir-lang/noir/issues/3010)) ([758b6b6](https://github.com/noir-lang/noir/commit/758b6b62918907c1a39f3090a77419003551745e)) +* **acvm:** Return false rather than panicking on invalid ECDSA signatures ([#2783](https://github.com/noir-lang/noir/issues/2783)) ([155abc0](https://github.com/noir-lang/noir/commit/155abc0d99fff41c79163c16bf297d41e5dff0fa)) +* Determinism of fallback transformer ([#3100](https://github.com/noir-lang/noir/issues/3100)) ([12daad1](https://github.com/noir-lang/noir/commit/12daad19c902caf5ee9e2eb4b6847bde5a924353)) +* Fix method `program_counter`, change method signature ([#3012](https://github.com/noir-lang/noir/issues/3012)) ([5ea522b](https://github.com/noir-lang/noir/commit/5ea522b840ca0f6f90d02ca00f0de32f515d450f)) +* Minor problems with `aztec` publishing ([#3095](https://github.com/noir-lang/noir/issues/3095)) ([0fc8f20](https://github.com/noir-lang/noir/commit/0fc8f20b8b87d033d27ce18db039399c17f81837)) +* Prevent duplicated assert message transformation ([#3038](https://github.com/noir-lang/noir/issues/3038)) ([082a6d0](https://github.com/noir-lang/noir/commit/082a6d02dad67a25692bed15c340a16a848a320e)) +* Return error rather than panicking on unreadable circuits ([#3179](https://github.com/noir-lang/noir/issues/3179)) ([d4f61d3](https://github.com/noir-lang/noir/commit/d4f61d3d51d515e40a5fd02d35315889f841bf53)) + + +### Miscellaneous Chores + +* Move circuit serialization circuit into acir ([#3345](https://github.com/noir-lang/noir/issues/3345)) ([122119b](https://github.com/noir-lang/noir/commit/122119b7377cec1b7c42c586c64b69b3bdf4d539)) + +## [0.35.0](https://github.com/noir-lang/noir/compare/v0.34.0...v0.35.0) (2023-11-28) + + +### ⚠ BREAKING CHANGES + +* Move circuit serialization circuit into acir ([#3345](https://github.com/noir-lang/noir/issues/3345)) +* expose pedersen hash in acir and bb solver ([#3269](https://github.com/noir-lang/noir/issues/3269)) +* Switch to new pedersen implementation ([#3151](https://github.com/noir-lang/noir/issues/3151)) +* Pass ACIR to ACVM by reference rather than passing ownership ([#2872](https://github.com/noir-lang/noir/issues/2872)) +* **wasm:** improve and simplify wasm compiler interface ([#2976](https://github.com/noir-lang/noir/issues/2976)) +* Maintain shape of foreign call arguments ([#2935](https://github.com/noir-lang/noir/issues/2935)) + +### Features + +* **acvm_js:** Export black box solver functions ([#2812](https://github.com/noir-lang/noir/issues/2812)) ([da8a98e](https://github.com/noir-lang/noir/commit/da8a98ed312fe69cb0bdb8f9d0a70ee7a981398f)) +* **acvm:** Separate ACVM optimizations and transformations ([#2979](https://github.com/noir-lang/noir/issues/2979)) ([5865d1a](https://github.com/noir-lang/noir/commit/5865d1a1bca16e1853663c71f893ff81fa3f7185)) +* Add ACIR serializer C++ codegen ([#2961](https://github.com/noir-lang/noir/issues/2961)) ([7556982](https://github.com/noir-lang/noir/commit/7556982dbebe25eaa17240abbe270b771b55de45)) +* Add conditional compilation of methods based on the underlying field being used ([#3045](https://github.com/noir-lang/noir/issues/3045)) ([2e008e2](https://github.com/noir-lang/noir/commit/2e008e2438795bbc41b0641e830378b76bf2e194)) +* Add debugger commands to introspect (and modify) the current state ([#3391](https://github.com/noir-lang/noir/issues/3391)) ([9e1ad85](https://github.com/noir-lang/noir/commit/9e1ad858cf8a1d9aba0137abe6a749267498bfaf)) +* Expose pedersen hash in acir and bb solver ([#3269](https://github.com/noir-lang/noir/issues/3269)) ([0108b6c](https://github.com/noir-lang/noir/commit/0108b6c1e8dc0dfc766ab3c4944deae9354dec36)) +* Extract Brillig VM to allow step debugging ([#3259](https://github.com/noir-lang/noir/issues/3259)) ([f6431f9](https://github.com/noir-lang/noir/commit/f6431f99711f15a96a4f7fed2f413daece94b5e1)) +* Implement euclidean division and signed division in terms of `AcirVar`s ([#3230](https://github.com/noir-lang/noir/issues/3230)) ([b8b7782](https://github.com/noir-lang/noir/commit/b8b77825410c0e1f95549259a51e2c40de1ec342)) +* Maintain shape of foreign call arguments ([#2935](https://github.com/noir-lang/noir/issues/2935)) ([f7869e6](https://github.com/noir-lang/noir/commit/f7869e6fb492b617e776e538ac4babfa56261d26)) +* Pass ACIR to ACVM by reference rather than passing ownership ([#2872](https://github.com/noir-lang/noir/issues/2872)) ([b3a9c34](https://github.com/noir-lang/noir/commit/b3a9c343993ce3207de62106bda6cb2b2ef3de50)) +* Pass brillig bytecode to VM by reference ([#3030](https://github.com/noir-lang/noir/issues/3030)) ([4ee290b](https://github.com/noir-lang/noir/commit/4ee290b8b6f75bc1974a5750248570eeca8d244e)) +* Refactor debugger and separate core from UI ([#3308](https://github.com/noir-lang/noir/issues/3308)) ([8466810](https://github.com/noir-lang/noir/commit/846681079ab7295b201480a5c8baebc45e858c6f)) +* Replace boolean range constraints with arithmetic opcodes ([#3234](https://github.com/noir-lang/noir/issues/3234)) ([949222c](https://github.com/noir-lang/noir/commit/949222c20d9e65152e3814d02da1c4c41ffc23a5)) +* Save Brillig execution state in ACVM ([#3026](https://github.com/noir-lang/noir/issues/3026)) ([88682da](https://github.com/noir-lang/noir/commit/88682da87ffc9e26da5c9e4b5a4d8e62a6ee43c6)) +* Solve `fixed_base_scalar_mul` black box functions in rust ([#3153](https://github.com/noir-lang/noir/issues/3153)) ([1c1afbc](https://github.com/noir-lang/noir/commit/1c1afbcddf0b5fdb39f00ad28ae90caf699d1265)) +* Switch to new pedersen implementation ([#3151](https://github.com/noir-lang/noir/issues/3151)) ([35fb3f7](https://github.com/noir-lang/noir/commit/35fb3f7076d52db7ca3bef0a70a3dbccaf82f58d)) +* **wasm:** Improve and simplify wasm compiler interface ([#2976](https://github.com/noir-lang/noir/issues/2976)) ([1b5124b](https://github.com/noir-lang/noir/commit/1b5124bc74f7ac5360db04b34d1b7b2284061fd3)) + + +### Bug Fixes + +* ACIR optimizer should update assertion messages ([#3010](https://github.com/noir-lang/noir/issues/3010)) ([758b6b6](https://github.com/noir-lang/noir/commit/758b6b62918907c1a39f3090a77419003551745e)) +* **acvm:** Return false rather than panicking on invalid ECDSA signatures ([#2783](https://github.com/noir-lang/noir/issues/2783)) ([155abc0](https://github.com/noir-lang/noir/commit/155abc0d99fff41c79163c16bf297d41e5dff0fa)) +* Determinism of fallback transformer ([#3100](https://github.com/noir-lang/noir/issues/3100)) ([12daad1](https://github.com/noir-lang/noir/commit/12daad19c902caf5ee9e2eb4b6847bde5a924353)) +* Fix method `program_counter`, change method signature ([#3012](https://github.com/noir-lang/noir/issues/3012)) ([5ea522b](https://github.com/noir-lang/noir/commit/5ea522b840ca0f6f90d02ca00f0de32f515d450f)) +* Minor problems with `aztec` publishing ([#3095](https://github.com/noir-lang/noir/issues/3095)) ([0fc8f20](https://github.com/noir-lang/noir/commit/0fc8f20b8b87d033d27ce18db039399c17f81837)) +* Prevent duplicated assert message transformation ([#3038](https://github.com/noir-lang/noir/issues/3038)) ([082a6d0](https://github.com/noir-lang/noir/commit/082a6d02dad67a25692bed15c340a16a848a320e)) +* Return error rather than panicking on unreadable circuits ([#3179](https://github.com/noir-lang/noir/issues/3179)) ([d4f61d3](https://github.com/noir-lang/noir/commit/d4f61d3d51d515e40a5fd02d35315889f841bf53)) + + +### Miscellaneous Chores + +* Move circuit serialization circuit into acir ([#3345](https://github.com/noir-lang/noir/issues/3345)) ([122119b](https://github.com/noir-lang/noir/commit/122119b7377cec1b7c42c586c64b69b3bdf4d539)) + +## [0.34.0](https://github.com/noir-lang/noir/compare/v0.33.0...v0.34.0) (2023-11-22) + + +### ⚠ BREAKING CHANGES + +* Move circuit serialization circuit into acir ([#3345](https://github.com/noir-lang/noir/issues/3345)) +* expose pedersen hash in acir and bb solver ([#3269](https://github.com/noir-lang/noir/issues/3269)) +* Switch to new pedersen implementation ([#3151](https://github.com/noir-lang/noir/issues/3151)) +* Pass ACIR to ACVM by reference rather than passing ownership ([#2872](https://github.com/noir-lang/noir/issues/2872)) +* **wasm:** improve and simplify wasm compiler interface ([#2976](https://github.com/noir-lang/noir/issues/2976)) +* Maintain shape of foreign call arguments ([#2935](https://github.com/noir-lang/noir/issues/2935)) + +### Features + +* **acvm_js:** Export black box solver functions ([#2812](https://github.com/noir-lang/noir/issues/2812)) ([da8a98e](https://github.com/noir-lang/noir/commit/da8a98ed312fe69cb0bdb8f9d0a70ee7a981398f)) +* **acvm:** Separate ACVM optimizations and transformations ([#2979](https://github.com/noir-lang/noir/issues/2979)) ([5865d1a](https://github.com/noir-lang/noir/commit/5865d1a1bca16e1853663c71f893ff81fa3f7185)) +* Add ACIR serializer C++ codegen ([#2961](https://github.com/noir-lang/noir/issues/2961)) ([7556982](https://github.com/noir-lang/noir/commit/7556982dbebe25eaa17240abbe270b771b55de45)) +* Add conditional compilation of methods based on the underlying field being used ([#3045](https://github.com/noir-lang/noir/issues/3045)) ([2e008e2](https://github.com/noir-lang/noir/commit/2e008e2438795bbc41b0641e830378b76bf2e194)) +* Add debugger commands to introspect (and modify) the current state ([#3391](https://github.com/noir-lang/noir/issues/3391)) ([9e1ad85](https://github.com/noir-lang/noir/commit/9e1ad858cf8a1d9aba0137abe6a749267498bfaf)) +* Expose pedersen hash in acir and bb solver ([#3269](https://github.com/noir-lang/noir/issues/3269)) ([0108b6c](https://github.com/noir-lang/noir/commit/0108b6c1e8dc0dfc766ab3c4944deae9354dec36)) +* Extract Brillig VM to allow step debugging ([#3259](https://github.com/noir-lang/noir/issues/3259)) ([f6431f9](https://github.com/noir-lang/noir/commit/f6431f99711f15a96a4f7fed2f413daece94b5e1)) +* Implement euclidean division and signed division in terms of `AcirVar`s ([#3230](https://github.com/noir-lang/noir/issues/3230)) ([b8b7782](https://github.com/noir-lang/noir/commit/b8b77825410c0e1f95549259a51e2c40de1ec342)) +* Maintain shape of foreign call arguments ([#2935](https://github.com/noir-lang/noir/issues/2935)) ([f7869e6](https://github.com/noir-lang/noir/commit/f7869e6fb492b617e776e538ac4babfa56261d26)) +* Pass ACIR to ACVM by reference rather than passing ownership ([#2872](https://github.com/noir-lang/noir/issues/2872)) ([b3a9c34](https://github.com/noir-lang/noir/commit/b3a9c343993ce3207de62106bda6cb2b2ef3de50)) +* Pass brillig bytecode to VM by reference ([#3030](https://github.com/noir-lang/noir/issues/3030)) ([4ee290b](https://github.com/noir-lang/noir/commit/4ee290b8b6f75bc1974a5750248570eeca8d244e)) +* Refactor debugger and separate core from UI ([#3308](https://github.com/noir-lang/noir/issues/3308)) ([8466810](https://github.com/noir-lang/noir/commit/846681079ab7295b201480a5c8baebc45e858c6f)) +* Replace boolean range constraints with arithmetic opcodes ([#3234](https://github.com/noir-lang/noir/issues/3234)) ([949222c](https://github.com/noir-lang/noir/commit/949222c20d9e65152e3814d02da1c4c41ffc23a5)) +* Save Brillig execution state in ACVM ([#3026](https://github.com/noir-lang/noir/issues/3026)) ([88682da](https://github.com/noir-lang/noir/commit/88682da87ffc9e26da5c9e4b5a4d8e62a6ee43c6)) +* Solve `fixed_base_scalar_mul` black box functions in rust ([#3153](https://github.com/noir-lang/noir/issues/3153)) ([1c1afbc](https://github.com/noir-lang/noir/commit/1c1afbcddf0b5fdb39f00ad28ae90caf699d1265)) +* Switch to new pedersen implementation ([#3151](https://github.com/noir-lang/noir/issues/3151)) ([35fb3f7](https://github.com/noir-lang/noir/commit/35fb3f7076d52db7ca3bef0a70a3dbccaf82f58d)) +* **wasm:** Improve and simplify wasm compiler interface ([#2976](https://github.com/noir-lang/noir/issues/2976)) ([1b5124b](https://github.com/noir-lang/noir/commit/1b5124bc74f7ac5360db04b34d1b7b2284061fd3)) + + +### Bug Fixes + +* ACIR optimizer should update assertion messages ([#3010](https://github.com/noir-lang/noir/issues/3010)) ([758b6b6](https://github.com/noir-lang/noir/commit/758b6b62918907c1a39f3090a77419003551745e)) +* **acvm:** Return false rather than panicking on invalid ECDSA signatures ([#2783](https://github.com/noir-lang/noir/issues/2783)) ([155abc0](https://github.com/noir-lang/noir/commit/155abc0d99fff41c79163c16bf297d41e5dff0fa)) +* Determinism of fallback transformer ([#3100](https://github.com/noir-lang/noir/issues/3100)) ([12daad1](https://github.com/noir-lang/noir/commit/12daad19c902caf5ee9e2eb4b6847bde5a924353)) +* Fix method `program_counter`, change method signature ([#3012](https://github.com/noir-lang/noir/issues/3012)) ([5ea522b](https://github.com/noir-lang/noir/commit/5ea522b840ca0f6f90d02ca00f0de32f515d450f)) +* Minor problems with `aztec` publishing ([#3095](https://github.com/noir-lang/noir/issues/3095)) ([0fc8f20](https://github.com/noir-lang/noir/commit/0fc8f20b8b87d033d27ce18db039399c17f81837)) +* Prevent duplicated assert message transformation ([#3038](https://github.com/noir-lang/noir/issues/3038)) ([082a6d0](https://github.com/noir-lang/noir/commit/082a6d02dad67a25692bed15c340a16a848a320e)) +* Return error rather than panicking on unreadable circuits ([#3179](https://github.com/noir-lang/noir/issues/3179)) ([d4f61d3](https://github.com/noir-lang/noir/commit/d4f61d3d51d515e40a5fd02d35315889f841bf53)) + + +### Miscellaneous Chores + +* Move circuit serialization circuit into acir ([#3345](https://github.com/noir-lang/noir/issues/3345)) ([122119b](https://github.com/noir-lang/noir/commit/122119b7377cec1b7c42c586c64b69b3bdf4d539)) + ## [0.33.0](https://github.com/noir-lang/noir/compare/v0.32.0...v0.33.0) (2023-11-07) diff --git a/acvm-repo/acir/Cargo.toml b/acvm-repo/acir/Cargo.toml index 25d770e1f1..100ab06aff 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.33.0" +version = "0.37.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acir/acir_docs.md b/acvm-repo/acir/acir_docs.md new file mode 100644 index 0000000000..eb532c9ae0 --- /dev/null +++ b/acvm-repo/acir/acir_docs.md @@ -0,0 +1,206 @@ +# ACIR documentation (draft) + +## Abstract +This document describes the purpose of ACIR, what it is and how ACIR programs can be used by compilers and proving systems. It is intended to be a reference documentation for ACIR. + +## Introduction +The purpose of ACIR is to make the link between a generic proving system, such as Aztec's Barretenberg, and a frontend, such as Noir, which describes user-specific computations. + +More precisely, Noir is a programming language for zero-knowledge proofs (ZKP) which allows users to write programs in an intuitive way using a high-level language close to Rust syntax. Noir is able to generate a proof of execution of a Noir program, using an external proving system. However, proving systems uses specific low-level constrain-based languages. Similarly, frontends have their own internal representation in order to represent user programs. + +The goal of ACIR is to provide a generic open-source intermediate representation close to proving system 'languages', but agnostic to a specific proving system, that can be used both by proving system as well as a target for frontends. So, at the end of the day, an ACIR program is just another representation of a program, dedicated to proving systems. + +## Abstract Circuit Intermediate Representation +ACIR stands for abstract circuit intermediate representation: +- **abstract circuit**: circuits are a simple computation model where basic computation units, named gates, are connected with wires. Data flows through the wires while gates compute output wires based on their input. More formally, they are directed acyclic graphs (DAG) where the vertices are the gates and the edges are the wires. Due to the immutability nature of the wires (their value does not change during an execution), they are well suited for describing computations for ZKPs. Furthermore, we do not lose any expressiveness when using a circuit as it is well known that any bounded computation can be translated into an arithmetic circuit (i.e a circuit with only addition and multiplication gates). +The term abstract here simply mean that we do not refer to an actual physical circuit (such as an electronic circuit). Furthermore, we will not exactly use the circuit model, but another model even better suited to ZKPs, the constraint model (see below). +- **intermediate representation**: The ACIR representation is intermediate because it lies between a frontend and its proving system. ACIR bytecode makes the link between noir compiler output and the proving system backend input. + +## The constraint model +The first step for generating a proof that a specific program was executed, is to execute this program. Since the proving system is going to handle ACIR programs, we need in fact to execute an ACIR program, using the user-supplied inputs. + +In ACIR terminology, the gates are called opcodes and the wires are called partial witnesses. However, instead of connecting the opcodes together through wires, we create constraints: an opcode constraints together a set of wires. +This constraint model trivially supersedes the circuit model. For instance, an addition gate output_wire = input_wire_1 + input_wire_2 can be expressed with the following arithmetic constraint: output_wire - (input_wire_1 + input_wire_2) = 0 + + + +## Solving +Because of these constraints, executing an ACIR program is called solving the witnesses. From the witnesses representing the inputs of the program, whose values are supplied by the user, we find out what the other witnesses should be by executing/solving the constraints one-by-one in the order they were defined. + +For instance, if input_wire_1 and input_wire_2 values are supplied as 3 and 8, then we can solve the opcode output_wire - (input_wire_1 + input_wire_2) = 0 by saying that output_wire is 11. + +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 +3. witness assignement + ACIR -> (proving system) proof + + +Although the ordering of opcode does not matter in theory, since a system of equations is not dependent on its ordering, in practice it matters a lot for the solving (i.e the performance of the execution). ACIR opcodes **must be ordered** so that each opcode can be resolved one after the other. + + +The values of the witnesses lie in the scalar field of the proving system. We will refer to it as FieldElement or ACIR field. The proving system need the values of all the partial witnesses and all the constraints in order to generate a proof. + + +*Remark*: The value of a partial witness is unique and fixed throughout a program execution, although in some rare cases, multiple values are possible for a same execution and witness (when there are several valid solutions to the constraints). Having multiple possible values for a witness may indicate that the circuit is not safe. + +*Remark*: Why do we use the term partial witnesses? It is because the proving system may create other constraints and witnesses (especially with BlackBoxFuncCall, see below). A proof refers to a full witness assignements and their constraints. ACIR opcodes and their partial witnesses are still an intermediate representation before getting the full list of constraints and witnesses. For the sake of simplicity, we will refer to witness instead of partial witness from now on. + + +## ACIR Reference +We assume here that the proving system is Barretenberg. Some parameters may slightly change with another proving system, in particular the bit size of FieldElement, which is 254 for Barretenberg. + +Some opcodes have inputs and outputs, which means that the output is constrained to be the result of the opcode computation from the inputs. The solver expects that all inputs are known when solving such opcodes. + +Some opcodes are not constrained, which mean they will not be used by the 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). + +*Remark*: Opcodes operate on witnesses, but we will see that some opcode work on Arithmetic expressions of witnesses. We call an arithmetic expression a linear combination of witnesses and/or products of two witnesses (and also a constant term). A single witness is a (simple) arithmetic expression, and conversly, an arithmetic expression can be turned into a single witness using an arithmetic opcode (see below). So basically, using witnesses or arithmetic expressions is equivalent, but the latter can avoid the creation of witness in some cases. + +### Arithmetic opcode +An arithmetic 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 polynomial of total degree at most 2. +The coefficients ${q_M}_{i,j}, q_i,q_c$ of the polynomial are known values which define the opcode. +A general expression of arithmetic opcode is the following: $\sum_{i,j} {q_M}_{i,j}w_iw_j + \sum_i q_iw_i +q_c = 0$ + +An arithmetic opcode can be used to: +- **express a constraint** on witnesses; for instance to express that a witness $w$ is a boolean, you can add the opcode: $w*w-w=0$ +- or, to **compute the value** of an arithmetic operation of some inputs. For instance, to multiply two witnesses $x$ and $y$, you would use the opcode $z-x*y=0$, which would constraint $z$ to be $x*y$. + + +The solver expects that at most one witness is not known when executing the opcode. + +### BlackBoxFuncCall opcode +These opcodes represent a specific computation. Even if any computation can be done using only arithmetic opcodes, it is not always efficient. Some proving systems, and in particular the proving system from Aztec, can implement several computations more efficiently using for instance look-up tables. The BlackBoxFuncCall opcode is used to ask the proving system to handle the computation by itself. +All black box functions takes as input a tuple (witness, num_bits), where num_bits is a constant representing the bit size of the input witness, and they have one or several witnesses as output. +Some more advanced computations assume that the proving system has an 'embedded curve'. It is a curve that cycle with the main curve of the proving system, i.e the scalar field of the embedded curve is the base field of the main one, and vice-versa. The curves used by the proving system are dependent on the proving system (and/or its configuration). Aztec's Barretenberg uses BN254 as the main curve and Grumpkin as the embedded curve. + +The black box functions supported by ACIR are: + +**AND**: performs the bitwise AND of lhs and rhs. bit_size must be the same for both inputs. +- lhs: (witness, bit_size) +- rhs: (witness, bit_size) +- output: a witness whose value is constrained to be lhs AND rhs, as bit_size bit integers + +**XOR**: performs the bitwise XOR of lhs and rhs. bit_size must be the same for both inputs. +- lhs: (witness, bit_size) +- rhs: (witness, bit_size) +- output: a witness whose value is constrained to be lhs XOR rhs, as bit_size bit integers + +**RANGE**: constraint the input to be of the provided bit size +input: (witness, bit_size) + +**SHA256**: computes sha256 of the inputs +- inputs are a byte array, i.e a vector of (FieldElement, 8) +- output is a byte array of len 32, i.e a vector of 32 (FieldElement, 8), constrainted to be the sha256 of the inputs. + +**Blake2s**: computes the Blake2s hash of the inputs, as specified in https://tools.ietf.org/html/rfc7693 +- inputs are a byte array, i.e a vector of (FieldElement, 8) +- output is a byte array of length 32, i.e a vector of 32 (FieldElement, 8), constrainted to be the blake2s of the inputs. + + +**SchnorrVerify**: Verify a Schnorr signature over the embedded curve +- inputs are: + - Public key as 2 (FieldElement, 254) + - signature as a vector of 64 bytes (FieldElement, 8) + - message as a vector of (FieldElement, 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. + + +**PedersenCommitment**: Computes a Pedersen commitments of the inputs using generators of the embedded curve +- input: vector of (FieldElement, 254) +- output: 2 witnesses representing the x,y coordinates of the resulting Grumpkin point +- domain separator: a constant public value (a field element) that you can use so that the commitment also depends on the domain separator. Noir uses 0 as domain separator. + +The backend should handle proper conversion between the inputs being ACIR field elements and the scalar field of the embedded curve. In the case of Aztec's Barretenberg, the latter is bigger than the ACIR field so it is straightforward. The Peredersen generators are managed by the proving system. + + +**PedersenHash**: Computes a Pedersen commitments of the inputs and their number, using generators of the embedded curve +- input: vector of (FieldElement, 254) +- output: the x-coordinate of the pedersen commitment of the 'prepended input' (see below) +- domain separator: a constant public value (a field element) that you can use so that the hash also depends on the domain separator. Noir uses 0 as domain separator. + +In Barretenberg, PedersenHash is doing the same as PedersenCommitment, except that it prepends the inputs with their length. + + +**HashToField128Security**: This opcode is deprecated and will be removed. + +**EcdsaSecp256k1**: Verify an ECDSA signature over Secp256k1 +- inputs: + - x coordinate of public key as 32 bytes + - y coordinate of public key as 32 bytes + - 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. + +**EcdsaSecp256r1**: Same as EcdsaSecp256k1, but done over another curve. + +**FixedBaseScalarMul**: scalar multiplication with a fixed generator of the embedded curve +- input: low, high are 2 (field , 254), representing the low and high part of the input. For Barretenberg, they must both be less than 128 bits. +- output: x and y coordinates of $low*G+high*2^{128}*G$, where G is a fixed generator + +Because the Grumpkin scalar field is bigger than the ACIR field, we provide 2 ACIR fields representing the low and high parts of the Grumpkin scalar $a$: +$a=low+high*2^{128},$ with $low, high < 2^{128}$ + +**Keccak256**: Computes the Keccak-256 (Ethereum version) of the inputs. +- inputs: Vector of bytes (FieldElement, 8) +- outputs: Vector of 32 bytes (FieldElement, 8) + + +**Keccak256VariableLength**: Computes the Keccak-256 (Ethereum version) of the inputs, restricted to the given length. +- inputs: Vector of bytes (FieldElement, 8) +- var_message_size: number of inputs to hash; it must be less (or equal) than the inputs length +- outputs: a vector of 32 bytes (FieldElement, 8) + + + +**RecursiveAggregation**: verify a proof inside the circuit. +**Warning: this opcode is subject to change.** +- verification_key: Vector of (FieldElement, 254) representing the verification key of the circuit being verified +- public_inputs: Vector of (FieldElement, 254) representing the public inputs corresponding to the proof being verified +- key_hash: one (FieldElement, 254). It should be the hash of the verification key. Barretenberg expects the Pedersen hash of the verification key +- input_aggregation_object: an optional vector of (FieldElement, 254). It is a blob of data specific to the proving sytem. +- output_aggregation_object: Some witnesses returned by the function, representing some data internal to the proving system. + +This black box function does not fully verify a proof, what it does is verifying that the key_hash is indeed a hash of verification_key, allowing the user to use the verification key as private inputs and only have the key_hash as public input, which is more performant. +Another thing that it does is preparing the verification of the proof. In order to fully verify a proof, some operations may still be required to be done by the final verifier. This is why this black box function does not say if verification is passing or not. +If you have several proofs to verify in one ACIR program, you would call RecursiveAggregation() multiple times and passing the output_aggregation_object as input_aggregation_object to the next RecursiveAggregation() call, except for the first call where you do not have any input_aggregation_object. +If one of the proof you verify with the black box function does not verify, then the verification of the proof of the main ACIR program will ultimately fail. + + +### Brillig +This opcode is used as a hint for the solver when executing (solving) the circuit. The opcode does not generate any constraint and is usually the result of the compilation of an unconstrained noir function. +- inputs: inputs to the opcode, as 'arithmetic expressions'. +- outputs: opcode outputs, as witnesses +- bytecode: assembly code representing the computation to perform within this opcode. The noir assembly specification is not part of this document. +- predicate: an arithmetic expression that disable the opcode when it is null. + +Let's see an example with euclidian division. +The normal way to compute a/b, where a and b are 8-bits integers, is to implement Euclid algorithm which computes in a loop (or recursively) modulos of the kind 'a mod b'. Doing this computation requires a lot of steps to be properly implemented in ACIR, especially the loop with a condition. However, euclidian division can be easily constrained with one arithmetic opcode: a = bq+r, assuming q is 8 bits and r Self { - match bb_func { - BlackBoxFunc::AND => BlackBoxFuncCall::AND { - lhs: FunctionInput::dummy(), - rhs: FunctionInput::dummy(), - output: Witness(0), - }, - BlackBoxFunc::XOR => BlackBoxFuncCall::XOR { - lhs: FunctionInput::dummy(), - rhs: FunctionInput::dummy(), - output: Witness(0), - }, - BlackBoxFunc::RANGE => BlackBoxFuncCall::RANGE { input: FunctionInput::dummy() }, - BlackBoxFunc::SHA256 => BlackBoxFuncCall::SHA256 { inputs: vec![], outputs: vec![] }, - BlackBoxFunc::Blake2s => BlackBoxFuncCall::Blake2s { inputs: vec![], outputs: vec![] }, - BlackBoxFunc::Blake3 => BlackBoxFuncCall::Blake3 { inputs: vec![], outputs: vec![] }, - BlackBoxFunc::SchnorrVerify => BlackBoxFuncCall::SchnorrVerify { - public_key_x: FunctionInput::dummy(), - public_key_y: FunctionInput::dummy(), - signature: vec![], - message: vec![], - output: Witness(0), - }, - BlackBoxFunc::PedersenCommitment => BlackBoxFuncCall::PedersenCommitment { - inputs: vec![], - domain_separator: 0, - outputs: (Witness(0), Witness(0)), - }, - BlackBoxFunc::PedersenHash => BlackBoxFuncCall::PedersenHash { - inputs: vec![], - domain_separator: 0, - output: Witness(0), - }, - BlackBoxFunc::HashToField128Security => { - BlackBoxFuncCall::HashToField128Security { inputs: vec![], output: Witness(0) } - } - BlackBoxFunc::EcdsaSecp256k1 => BlackBoxFuncCall::EcdsaSecp256k1 { - public_key_x: vec![], - public_key_y: vec![], - signature: vec![], - hashed_message: vec![], - output: Witness(0), - }, - BlackBoxFunc::EcdsaSecp256r1 => BlackBoxFuncCall::EcdsaSecp256r1 { - public_key_x: vec![], - public_key_y: vec![], - signature: vec![], - hashed_message: vec![], - output: Witness(0), - }, - BlackBoxFunc::FixedBaseScalarMul => BlackBoxFuncCall::FixedBaseScalarMul { - low: FunctionInput::dummy(), - high: FunctionInput::dummy(), - outputs: (Witness(0), Witness(0)), - }, - BlackBoxFunc::Keccak256 => { - BlackBoxFuncCall::Keccak256 { inputs: vec![], outputs: vec![] } - } - BlackBoxFunc::RecursiveAggregation => BlackBoxFuncCall::RecursiveAggregation { - verification_key: vec![], - proof: vec![], - public_inputs: vec![], - key_hash: FunctionInput::dummy(), - input_aggregation_object: None, - output_aggregation_object: vec![], - }, - } - } - pub fn get_black_box_func(&self) -> BlackBoxFunc { match self { BlackBoxFuncCall::AND { .. } => BlackBoxFunc::AND, diff --git a/acvm-repo/acir_field/Cargo.toml b/acvm-repo/acir_field/Cargo.toml index 2cd2801db1..76030bc886 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.33.0" +version = "0.37.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acir_field/src/generic_ark.rs b/acvm-repo/acir_field/src/generic_ark.rs index 0f4be21ad5..5c70d3cda3 100644 --- a/acvm-repo/acir_field/src/generic_ark.rs +++ b/acvm-repo/acir_field/src/generic_ark.rs @@ -143,6 +143,12 @@ impl From for FieldElement { } } +impl From for FieldElement { + fn from(a: usize) -> FieldElement { + FieldElement::from(a as u128) + } +} + impl From for FieldElement { fn from(boolean: bool) -> FieldElement { if boolean { @@ -266,7 +272,10 @@ impl FieldElement { } pub fn from_hex(hex_str: &str) -> Option> { let value = hex_str.strip_prefix("0x").unwrap_or(hex_str); - let hex_as_bytes = hex::decode(value).ok()?; + // Values of odd length require an additional "0" prefix + let sanitized_value = + if value.len() % 2 == 0 { value.to_string() } else { format!("0{}", value) }; + let hex_as_bytes = hex::decode(sanitized_value).ok()?; Some(FieldElement::from_be_bytes_reduce(&hex_as_bytes)) } @@ -440,6 +449,25 @@ mod tests { assert_eq!(minus_i_field_element.to_hex(), string); } } + + #[test] + fn deserialize_even_and_odd_length_hex() { + // Test cases of (odd, even) length hex strings + let hex_strings = + vec![("0x0", "0x00"), ("0x1", "0x01"), ("0x002", "0x0002"), ("0x00003", "0x000003")]; + for (i, case) in hex_strings.into_iter().enumerate() { + let i_field_element = + crate::generic_ark::FieldElement::::from(i as i128); + let odd_field_element = + crate::generic_ark::FieldElement::::from_hex(case.0).unwrap(); + let even_field_element = + crate::generic_ark::FieldElement::::from_hex(case.1).unwrap(); + + assert_eq!(i_field_element, odd_field_element); + assert_eq!(odd_field_element, even_field_element); + } + } + #[test] fn max_num_bits_smoke() { let max_num_bits_bn254 = crate::generic_ark::FieldElement::::max_num_bits(); diff --git a/acvm-repo/acvm/Cargo.toml b/acvm-repo/acvm/Cargo.toml index 032d93230d..6e4c2d322b 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.33.0" +version = "0.37.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acvm_js/Cargo.toml b/acvm-repo/acvm_js/Cargo.toml index e287ac9ed1..f6054b49de 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.33.0" +version = "0.37.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -26,9 +26,9 @@ wasm-bindgen-futures.workspace = true console_error_panic_hook.workspace = true gloo-utils.workspace = true js-sys.workspace = true +log.workspace = true serde = { version = "1.0.136", features = ["derive"] } -log = "0.4.17" wasm-logger = "0.2.0" const-str = "0.5.5" diff --git a/acvm-repo/acvm_js/build.sh b/acvm-repo/acvm_js/build.sh index 37f2fd0a5a..24af149bce 100755 --- a/acvm-repo/acvm_js/build.sh +++ b/acvm-repo/acvm_js/build.sh @@ -34,7 +34,7 @@ export CARGO_TARGET_DIR=$self_path/target rm -rf $self_path/outputs >/dev/null 2>&1 rm -rf $self_path/result >/dev/null 2>&1 -if [ -v out ]; then +if [ -n "$out" ]; then echo "Will install package to $out (defined outside installPhase.sh script)" else export out="$self_path/outputs/out" diff --git a/acvm-repo/acvm_js/package.json b/acvm-repo/acvm_js/package.json index 19090022e2..a890ca4008 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.33.0", + "version": "0.37.0", "repository": { "type": "git", "url": "https://github.com/noir-lang/acvm.git" diff --git a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml b/acvm-repo/barretenberg_blackbox_solver/Cargo.toml index 6917e7fbf8..bcf02eeab0 100644 --- a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml +++ b/acvm-repo/barretenberg_blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "barretenberg_blackbox_solver" description = "A wrapper around a barretenberg WASM binary to execute black box functions for which there is no rust implementation" # x-release-please-start-version -version = "0.33.0" +version = "0.37.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index ad0862afe4..b22ddc9ae0 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.33.0" +version = "0.37.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/brillig/Cargo.toml b/acvm-repo/brillig/Cargo.toml index 542839a576..47f9b3f429 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.33.0" +version = "0.37.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/brillig_vm/Cargo.toml b/acvm-repo/brillig_vm/Cargo.toml index 2d89aa7aa1..8c533352dd 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.33.0" +version = "0.37.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/stdlib/Cargo.toml b/acvm-repo/stdlib/Cargo.toml index 63a8b71eb1..de50d112df 100644 --- a/acvm-repo/stdlib/Cargo.toml +++ b/acvm-repo/stdlib/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_stdlib" description = "The ACVM standard library." # x-release-please-start-version -version = "0.33.0" +version = "0.37.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/aztec_macros/Cargo.toml b/aztec_macros/Cargo.toml new file mode 100644 index 0000000000..04f74d3b02 --- /dev/null +++ b/aztec_macros/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "aztec_macros" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +repository.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +noirc_frontend.workspace = true +iter-extended.workspace = true diff --git a/aztec_macros/src/lib.rs b/aztec_macros/src/lib.rs new file mode 100644 index 0000000000..1b433c33df --- /dev/null +++ b/aztec_macros/src/lib.rs @@ -0,0 +1,1025 @@ +use iter_extended::vecmap; + +use noirc_frontend::macros_api::FieldElement; +use noirc_frontend::macros_api::{ + BlockExpression, CallExpression, CastExpression, Distinctness, Expression, ExpressionKind, + ForLoopStatement, ForRange, FunctionDefinition, FunctionReturnType, FunctionVisibility, + HirContext, HirExpression, HirLiteral, HirStatement, Ident, ImportStatement, IndexExpression, + LetStatement, Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, NoirStruct, + Param, Path, PathKind, Pattern, PrefixExpression, SecondaryAttribute, Signedness, Span, + Statement, StatementKind, StructType, Type, TypeImpl, UnaryOp, UnresolvedType, + UnresolvedTypeData, Visibility, +}; +use noirc_frontend::macros_api::{CrateId, FileId}; +use noirc_frontend::macros_api::{MacroError, MacroProcessor}; +use noirc_frontend::macros_api::{ModuleDefId, NodeInterner, SortedModule, StructId}; + +pub struct AztecMacro; + +impl MacroProcessor for AztecMacro { + fn process_untyped_ast( + &self, + ast: SortedModule, + crate_id: &CrateId, + context: &HirContext, + ) -> Result { + transform(ast, crate_id, context) + } + + fn process_typed_ast(&self, crate_id: &CrateId, context: &mut HirContext) { + transform_hir(crate_id, context) + } +} + +#[derive(Debug, Clone)] +pub enum AztecMacroError { + AztecNotFound, + AztecComputeNoteHashAndNullifierNotFound { span: Span }, +} + +impl From for MacroError { + fn from(err: AztecMacroError) -> Self { + match err { + AztecMacroError::AztecNotFound {} => MacroError { + primary_message: "Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml. For more information go to https://docs.aztec.network/dev_docs/debugging/aztecnr-errors#aztec-dependency-not-found-please-add-aztec-as-a-dependency-in-your-nargotoml".to_owned(), + secondary_message: None, + span: None, + }, + AztecMacroError::AztecComputeNoteHashAndNullifierNotFound { span } => MacroError { + primary_message: "compute_note_hash_and_nullifier function not found. Define it in your contract. For more information go to https://docs.aztec.network/dev_docs/debugging/aztecnr-errors#compute_note_hash_and_nullifier-function-not-found-define-it-in-your-contract".to_owned(), + secondary_message: None, + span: Some(span), + }, + } + } +} + +// +// Helper macros for creating noir ast nodes +// +fn ident(name: &str) -> Ident { + Ident::new(name.to_string(), Span::default()) +} + +fn ident_path(name: &str) -> Path { + Path::from_ident(ident(name)) +} + +fn path(ident: Ident) -> Path { + Path::from_ident(ident) +} + +fn expression(kind: ExpressionKind) -> Expression { + Expression::new(kind, Span::default()) +} + +fn variable(name: &str) -> Expression { + expression(ExpressionKind::Variable(ident_path(name))) +} + +fn variable_ident(identifier: Ident) -> Expression { + expression(ExpressionKind::Variable(path(identifier))) +} + +fn variable_path(path: Path) -> Expression { + expression(ExpressionKind::Variable(path)) +} + +fn method_call(object: Expression, method_name: &str, arguments: Vec) -> Expression { + expression(ExpressionKind::MethodCall(Box::new(MethodCallExpression { + object, + method_name: ident(method_name), + arguments, + }))) +} + +fn call(func: Expression, arguments: Vec) -> Expression { + expression(ExpressionKind::Call(Box::new(CallExpression { func: Box::new(func), arguments }))) +} + +fn pattern(name: &str) -> Pattern { + Pattern::Identifier(ident(name)) +} + +fn mutable(name: &str) -> Pattern { + Pattern::Mutable(Box::new(pattern(name)), Span::default()) +} + +fn mutable_assignment(name: &str, assigned_to: Expression) -> Statement { + make_statement(StatementKind::Let(LetStatement { + pattern: mutable(name), + r#type: make_type(UnresolvedTypeData::Unspecified), + expression: assigned_to, + })) +} + +fn mutable_reference(variable_name: &str) -> Expression { + expression(ExpressionKind::Prefix(Box::new(PrefixExpression { + operator: UnaryOp::MutableReference, + rhs: variable(variable_name), + }))) +} + +fn assignment(name: &str, assigned_to: Expression) -> Statement { + make_statement(StatementKind::Let(LetStatement { + pattern: pattern(name), + r#type: make_type(UnresolvedTypeData::Unspecified), + expression: assigned_to, + })) +} + +fn member_access(lhs: &str, rhs: &str) -> Expression { + expression(ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { + lhs: variable(lhs), + rhs: ident(rhs), + }))) +} + +macro_rules! chained_path { + ( $base:expr $(, $tail:expr)* ) => { + { + let mut base_path = ident_path($base); + $( + base_path.segments.push(ident($tail)); + )* + base_path + } + } +} + +macro_rules! chained_dep { + ( $base:expr $(, $tail:expr)* ) => { + { + let mut base_path = ident_path($base); + base_path.kind = PathKind::Dep; + $( + base_path.segments.push(ident($tail)); + )* + base_path + } + } +} + +fn cast(lhs: Expression, ty: UnresolvedTypeData) -> Expression { + expression(ExpressionKind::Cast(Box::new(CastExpression { lhs, r#type: make_type(ty) }))) +} + +fn make_type(typ: UnresolvedTypeData) -> UnresolvedType { + UnresolvedType { typ, span: None } +} + +fn index_array(array: Ident, index: &str) -> Expression { + expression(ExpressionKind::Index(Box::new(IndexExpression { + collection: variable_path(path(array)), + index: variable(index), + }))) +} + +fn index_array_variable(array: Expression, index: &str) -> Expression { + expression(ExpressionKind::Index(Box::new(IndexExpression { + collection: array, + index: variable(index), + }))) +} + +fn import(path: Path) -> ImportStatement { + ImportStatement { path, alias: None } +} + +// +// Create AST Nodes for Aztec +// + +/// Traverses every function in the ast, calling `transform_function` which +/// determines if further processing is required +fn transform( + mut ast: SortedModule, + crate_id: &CrateId, + context: &HirContext, +) -> Result { + // Usage -> mut ast -> aztec_library::transform(&mut ast) + + // Covers all functions in the ast + for submodule in ast.submodules.iter_mut().filter(|submodule| submodule.is_contract) { + if transform_module(&mut submodule.contents, crate_id, context)? { + check_for_aztec_dependency(crate_id, context)?; + include_relevant_imports(&mut submodule.contents); + } + } + Ok(ast) +} + +// +// Transform Hir Nodes for Aztec +// + +/// Completes the Hir with data gathered from type resolution +fn transform_hir(crate_id: &CrateId, context: &mut HirContext) { + transform_events(crate_id, context); +} + +/// Includes an import to the aztec library if it has not been included yet +fn include_relevant_imports(ast: &mut SortedModule) { + // Create the aztec import path using the assumed chained_dep! macro + let aztec_import_path = import(chained_dep!("aztec")); + + // Check if the aztec import already exists + let is_aztec_imported = + ast.imports.iter().any(|existing_import| existing_import.path == aztec_import_path.path); + + // If aztec is not imported, add the import at the beginning + if !is_aztec_imported { + ast.imports.insert(0, aztec_import_path); + } +} + +/// Creates an error alerting the user that they have not downloaded the Aztec-noir library +fn check_for_aztec_dependency( + crate_id: &CrateId, + context: &HirContext, +) -> Result<(), (MacroError, FileId)> { + let crate_graph = &context.crate_graph[crate_id]; + let has_aztec_dependency = crate_graph.dependencies.iter().any(|dep| dep.as_name() == "aztec"); + if has_aztec_dependency { + Ok(()) + } else { + Err((AztecMacroError::AztecNotFound.into(), crate_graph.root_file_id)) + } +} + +// Check to see if the user has defined a storage struct +fn check_for_storage_definition(module: &SortedModule) -> bool { + module.types.iter().any(|r#struct| r#struct.name.0.contents == "Storage") +} + +// Check if "compute_note_hash_and_nullifier(Field,Field,Field,[Field; N]) -> [Field; 4]" is defined +fn check_for_compute_note_hash_and_nullifier_definition(module: &SortedModule) -> bool { + module.functions.iter().any(|func| { + func.def.name.0.contents == "compute_note_hash_and_nullifier" + && func.def.parameters.len() == 4 + && func.def.parameters[0].typ.typ == UnresolvedTypeData::FieldElement + && func.def.parameters[1].typ.typ == UnresolvedTypeData::FieldElement + && func.def.parameters[2].typ.typ == UnresolvedTypeData::FieldElement + // checks if the 4th parameter is an array and the Box in + // Array(Option, Box) contains only fields + && match &func.def.parameters[3].typ.typ { + UnresolvedTypeData::Array(_, inner_type) => { + matches!(inner_type.typ, UnresolvedTypeData::FieldElement) + }, + _ => false, + } + // We check the return type the same way as we did the 4th parameter + && match &func.def.return_type { + FunctionReturnType::Default(_) => false, + FunctionReturnType::Ty(unresolved_type) => { + match &unresolved_type.typ { + UnresolvedTypeData::Array(_, inner_type) => { + matches!(inner_type.typ, UnresolvedTypeData::FieldElement) + }, + _ => false, + } + } + } + }) +} + +/// Checks if an attribute is a custom attribute with a specific name +fn is_custom_attribute(attr: &SecondaryAttribute, attribute_name: &str) -> bool { + if let SecondaryAttribute::Custom(custom_attr) = attr { + custom_attr.as_str() == attribute_name + } else { + false + } +} + +/// Determines if ast nodes are annotated with aztec attributes. +/// For annotated functions it calls the `transform` function which will perform the required transformations. +/// Returns true if an annotated node is found, false otherwise +fn transform_module( + module: &mut SortedModule, + crate_id: &CrateId, + context: &HirContext, +) -> Result { + let mut has_transformed_module = false; + + // Check for a user defined storage struct + let storage_defined = check_for_storage_definition(module); + + if storage_defined && !check_for_compute_note_hash_and_nullifier_definition(module) { + let crate_graph = &context.crate_graph[crate_id]; + return Err(( + AztecMacroError::AztecComputeNoteHashAndNullifierNotFound { span: Span::default() } + .into(), + crate_graph.root_file_id, + )); + } + + for structure in module.types.iter() { + if structure.attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Event)) { + module.impls.push(generate_selector_impl(structure)); + has_transformed_module = true; + } + } + + for func in module.functions.iter_mut() { + for secondary_attribute in func.def.attributes.secondary.clone() { + if is_custom_attribute(&secondary_attribute, "aztec(private)") { + transform_function("Private", func, storage_defined); + has_transformed_module = true; + } else if is_custom_attribute(&secondary_attribute, "aztec(public)") { + transform_function("Public", func, storage_defined); + has_transformed_module = true; + } + } + // Add the storage struct to the beginning of the function if it is unconstrained in an aztec contract + if storage_defined && func.def.is_unconstrained { + transform_unconstrained(func); + has_transformed_module = true; + } + } + Ok(has_transformed_module) +} + +/// If it does, it will insert the following things: +/// - A new Input that is provided for a kernel app circuit, named: {Public/Private}ContextInputs +/// - Hashes all of the function input variables +/// - This instantiates a helper function +fn transform_function(ty: &str, func: &mut NoirFunction, storage_defined: bool) { + let context_name = format!("{}Context", ty); + let inputs_name = format!("{}ContextInputs", ty); + let return_type_name = format!("{}CircuitPublicInputs", ty); + + // Add access to the storage struct + if storage_defined { + let storage_def = abstract_storage(&ty.to_lowercase(), false); + func.def.body.0.insert(0, storage_def); + } + + // Insert the context creation as the first action + let create_context = create_context(&context_name, &func.def.parameters); + func.def.body.0.splice(0..0, (create_context).iter().cloned()); + + // Add the inputs to the params + let input = create_inputs(&inputs_name); + func.def.parameters.insert(0, input); + + // Abstract return types such that they get added to the kernel's return_values + if let Some(return_values) = abstract_return_values(func) { + func.def.body.0.push(return_values); + } + + // Push the finish method call to the end of the function + let finish_def = create_context_finish(); + func.def.body.0.push(finish_def); + + let return_type = create_return_type(&return_type_name); + func.def.return_type = return_type; + func.def.return_visibility = Visibility::Public; + + // Distinct return types are only required for private functions + // Public functions should have open auto-inferred + match ty { + "Private" => func.def.return_distinctness = Distinctness::Distinct, + "Public" => func.def.is_open = true, + _ => (), + } +} + +/// Transform Unconstrained +/// +/// Inserts the following code at the beginning of an unconstrained function +/// ```noir +/// let storage = Storage::init(Context::none()); +/// ``` +/// +/// This will allow developers to access their contract' storage struct in unconstrained functions +fn transform_unconstrained(func: &mut NoirFunction) { + func.def.body.0.insert(0, abstract_storage("Unconstrained", true)); +} + +fn collect_crate_structs(crate_id: &CrateId, context: &HirContext) -> Vec { + context + .def_map(crate_id) + .expect("ICE: Missing crate in def_map") + .modules() + .iter() + .flat_map(|(_, module)| { + module.type_definitions().filter_map(|typ| { + if let ModuleDefId::TypeId(struct_id) = typ { + Some(struct_id) + } else { + None + } + }) + }) + .collect() +} + +/// Substitutes the signature literal that was introduced in the selector method previously with the actual signature. +fn transform_event(struct_id: StructId, interner: &mut NodeInterner) { + let struct_type = interner.get_struct(struct_id); + let selector_id = interner + .lookup_method(&Type::Struct(struct_type, vec![]), struct_id, "selector", false) + .expect("Selector method not found"); + let selector_function = interner.function(&selector_id); + + let compute_selector_statement = interner.statement( + selector_function + .block(interner) + .statements() + .first() + .expect("Compute selector statement not found"), + ); + + let compute_selector_expression = match compute_selector_statement { + HirStatement::Expression(expression_id) => match interner.expression(&expression_id) { + HirExpression::Call(hir_call_expression) => Some(hir_call_expression), + _ => None, + }, + _ => None, + } + .expect("Compute selector statement is not a call expression"); + + let first_arg_id = compute_selector_expression + .arguments + .first() + .expect("Missing argument for compute selector"); + + match interner.expression(first_arg_id) { + HirExpression::Literal(HirLiteral::Str(signature)) + if signature == SIGNATURE_PLACEHOLDER => + { + let selector_literal_id = first_arg_id; + + let structure = interner.get_struct(struct_id); + let signature = event_signature(&structure.borrow()); + interner.update_expression(*selector_literal_id, |expr| { + *expr = HirExpression::Literal(HirLiteral::Str(signature.clone())); + }); + + // Also update the type! It might have a different length now than the placeholder. + interner.push_expr_type( + selector_literal_id, + Type::String(Box::new(Type::Constant(signature.len() as u64))), + ); + } + _ => unreachable!("Signature placeholder literal does not match"), + } +} + +fn transform_events(crate_id: &CrateId, context: &mut HirContext) { + for struct_id in collect_crate_structs(crate_id, context) { + let attributes = context.def_interner.struct_attributes(&struct_id); + if attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Event)) { + transform_event(struct_id, &mut context.def_interner); + } + } +} + +const SIGNATURE_PLACEHOLDER: &str = "SIGNATURE_PLACEHOLDER"; + +/// Generates the impl for an event selector +/// +/// Inserts the following code: +/// ```noir +/// impl SomeStruct { +/// fn selector() -> Field { +/// aztec::oracle::compute_selector::compute_selector("SIGNATURE_PLACEHOLDER") +/// } +/// } +/// ``` +/// +/// This allows developers to emit events without having to write the signature of the event every time they emit it. +/// The signature cannot be known at this point since types are not resolved yet, so we use a signature placeholder. +/// It'll get resolved after by transforming the HIR. +fn generate_selector_impl(structure: &NoirStruct) -> TypeImpl { + let struct_type = make_type(UnresolvedTypeData::Named(path(structure.name.clone()), vec![])); + + let selector_fun_body = BlockExpression(vec![make_statement(StatementKind::Expression(call( + variable_path(chained_path!("aztec", "selector", "compute_selector")), + vec![expression(ExpressionKind::Literal(Literal::Str(SIGNATURE_PLACEHOLDER.to_string())))], + )))]); + + let mut selector_fn_def = FunctionDefinition::normal( + &ident("selector"), + &vec![], + &[], + &selector_fun_body, + &[], + &FunctionReturnType::Ty(make_type(UnresolvedTypeData::FieldElement)), + ); + + selector_fn_def.visibility = FunctionVisibility::Public; + + // Seems to be necessary on contract modules + selector_fn_def.return_visibility = Visibility::Public; + + TypeImpl { + object_type: struct_type, + type_span: structure.span, + generics: vec![], + methods: vec![NoirFunction::normal(selector_fn_def)], + } +} + +/// Helper function that returns what the private context would look like in the ast +/// This should make it available to be consumed within aztec private annotated functions. +/// +/// The replaced code: +/// ```noir +/// /// Before +/// fn foo(inputs: PrivateContextInputs) { +/// // ... +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() { +/// // ... +/// } +fn create_inputs(ty: &str) -> Param { + let context_ident = ident("inputs"); + let context_pattern = Pattern::Identifier(context_ident); + let type_path = chained_path!("aztec", "abi", ty); + let context_type = make_type(UnresolvedTypeData::Named(type_path, vec![])); + let visibility = Visibility::Private; + + Param { pattern: context_pattern, typ: context_type, visibility, span: Span::default() } +} + +/// Creates the private context object to be accessed within the function, the parameters need to be extracted to be +/// appended into the args hash object. +/// +/// The replaced code: +/// ```noir +/// #[aztec(private)] +/// fn foo(structInput: SomeStruct, arrayInput: [u8; 10], fieldInput: Field) -> Field { +/// // Create the hasher object +/// let mut hasher = Hasher::new(); +/// +/// // struct inputs call serialize on them to add an array of fields +/// hasher.add_multiple(structInput.serialize()); +/// +/// // Array inputs are iterated over and each element is added to the hasher (as a field) +/// for i in 0..arrayInput.len() { +/// hasher.add(arrayInput[i] as Field); +/// } +/// // Field inputs are added to the hasher +/// hasher.add({ident}); +/// +/// // Create the context +/// // The inputs (injected by this `create_inputs`) and completed hash object are passed to the context +/// let mut context = PrivateContext::new(inputs, hasher.hash()); +/// } +/// ``` +fn create_context(ty: &str, params: &[Param]) -> Vec { + let mut injected_expressions: Vec = vec![]; + + // `let mut hasher = Hasher::new();` + let let_hasher = mutable_assignment( + "hasher", // Assigned to + call( + variable_path(chained_path!("aztec", "abi", "Hasher", "new")), // Path + vec![], // args + ), + ); + + // Completes: `let mut hasher = Hasher::new();` + injected_expressions.push(let_hasher); + + // Iterate over each of the function parameters, adding to them to the hasher + params.iter().for_each(|Param { pattern, typ, span: _, visibility: _ }| { + match pattern { + Pattern::Identifier(identifier) => { + // Match the type to determine the padding to do + let unresolved_type = &typ.typ; + let expression = match unresolved_type { + // `hasher.add_multiple({ident}.serialize())` + UnresolvedTypeData::Named(..) => add_struct_to_hasher(identifier), + UnresolvedTypeData::Array(_, arr_type) => { + add_array_to_hasher(identifier, arr_type) + } + // `hasher.add({ident})` + UnresolvedTypeData::FieldElement => add_field_to_hasher(identifier), + // Add the integer to the hasher, casted to a field + // `hasher.add({ident} as Field)` + UnresolvedTypeData::Integer(..) | UnresolvedTypeData::Bool => { + add_cast_to_hasher(identifier) + } + _ => unreachable!("[Aztec Noir] Provided parameter type is not supported"), + }; + injected_expressions.push(expression); + } + _ => todo!(), // Maybe unreachable? + } + }); + + // Create the inputs to the context + let inputs_expression = variable("inputs"); + // `hasher.hash()` + let hash_call = method_call( + variable("hasher"), // variable + "hash", // method name + vec![], // args + ); + + // let mut context = {ty}::new(inputs, hash); + let let_context = mutable_assignment( + "context", // Assigned to + call( + variable_path(chained_path!("aztec", "context", ty, "new")), // Path + vec![inputs_expression, hash_call], // args + ), + ); + injected_expressions.push(let_context); + + // Return all expressions that will be injected by the hasher + injected_expressions +} + +/// Abstract Return Type +/// +/// This function intercepts the function's current return type and replaces it with pushes +/// To the kernel +/// +/// The replaced code: +/// ```noir +/// /// Before +/// #[aztec(private)] +/// fn foo() -> abi::PrivateCircuitPublicInputs { +/// // ... +/// let my_return_value: Field = 10; +/// context.return_values.push(my_return_value); +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() -> Field { +/// // ... +/// let my_return_value: Field = 10; +/// my_return_value +/// } +/// ``` +/// Similarly; Structs will be pushed to the context, after serialize() is called on them. +/// Arrays will be iterated over and each element will be pushed to the context. +/// Any primitive type that can be cast will be casted to a field and pushed to the context. +fn abstract_return_values(func: &NoirFunction) -> Option { + let current_return_type = func.return_type().typ; + let len = func.def.body.len(); + let last_statement = &func.def.body.0[len - 1]; + + // TODO: (length, type) => We can limit the size of the array returned to be limited by kernel size + // Doesn't need done until we have settled on a kernel size + // TODO: support tuples here and in inputs -> convert into an issue + + // Check if the return type is an expression, if it is, we can handle it + match last_statement { + Statement { kind: StatementKind::Expression(expression), .. } => { + match current_return_type { + // Call serialize on structs, push the whole array, calling push_array + UnresolvedTypeData::Named(..) => Some(make_struct_return_type(expression.clone())), + UnresolvedTypeData::Array(..) => Some(make_array_return_type(expression.clone())), + // Cast these types to a field before pushing + UnresolvedTypeData::Bool | UnresolvedTypeData::Integer(..) => { + Some(make_castable_return_type(expression.clone())) + } + UnresolvedTypeData::FieldElement => Some(make_return_push(expression.clone())), + _ => None, + } + } + _ => None, + } +} + +/// Abstract storage +/// +/// For private functions: +/// ```noir +/// #[aztec(private)] +/// fn lol() { +/// let storage = Storage::init(Context::private(context)); +/// } +/// ``` +/// +/// For public functions: +/// ```noir +/// #[aztec(public)] +/// fn lol() { +/// let storage = Storage::init(Context::public(context)); +/// } +/// ``` +/// +/// For unconstrained functions: +/// ```noir +/// unconstrained fn lol() { +/// let storage = Storage::init(Context::none()); +/// } +fn abstract_storage(typ: &str, unconstrained: bool) -> Statement { + let init_context_call = if unconstrained { + call( + variable_path(chained_path!("aztec", "context", "Context", "none")), // Path + vec![], // args + ) + } else { + call( + variable_path(chained_path!("aztec", "context", "Context", typ)), // Path + vec![mutable_reference("context")], // args + ) + }; + + assignment( + "storage", // Assigned to + call( + variable_path(chained_path!("Storage", "init")), // Path + vec![init_context_call], // args + ), + ) +} + +/// Context Return Values +/// +/// Creates an instance to the context return values +/// ```noir +/// `context.return_values` +/// ``` +fn context_return_values() -> Expression { + member_access("context", "return_values") +} + +fn make_statement(kind: StatementKind) -> Statement { + Statement { span: Span::default(), kind } +} + +/// Make return Push +/// +/// Translates to: +/// `context.return_values.push({push_value})` +fn make_return_push(push_value: Expression) -> Statement { + make_statement(StatementKind::Semi(method_call( + context_return_values(), + "push", + vec![push_value], + ))) +} + +/// Make Return push array +/// +/// Translates to: +/// `context.return_values.push_array({push_value})` +fn make_return_push_array(push_value: Expression) -> Statement { + make_statement(StatementKind::Semi(method_call( + context_return_values(), + "push_array", + vec![push_value], + ))) +} + +/// Make struct return type +/// +/// Translates to: +/// ```noir +/// `context.return_values.push_array({push_value}.serialize())` +fn make_struct_return_type(expression: Expression) -> Statement { + let serialized_call = method_call( + expression, // variable + "serialize", // method name + vec![], // args + ); + make_return_push_array(serialized_call) +} + +/// Make array return type +/// +/// Translates to: +/// ```noir +/// for i in 0..{ident}.len() { +/// context.return_values.push({ident}[i] as Field) +/// } +/// ``` +fn make_array_return_type(expression: Expression) -> Statement { + let inner_cast_expression = + cast(index_array_variable(expression.clone(), "i"), UnresolvedTypeData::FieldElement); + let assignment = make_statement(StatementKind::Semi(method_call( + context_return_values(), // variable + "push", // method name + vec![inner_cast_expression], + ))); + + create_loop_over(expression, vec![assignment]) +} + +/// Castable return type +/// +/// Translates to: +/// ```noir +/// context.return_values.push({ident} as Field) +/// ``` +fn make_castable_return_type(expression: Expression) -> Statement { + // Cast these types to a field before pushing + let cast_expression = cast(expression, UnresolvedTypeData::FieldElement); + make_return_push(cast_expression) +} + +/// Create Return Type +/// +/// Public functions return abi::PublicCircuitPublicInputs while +/// private functions return abi::PrivateCircuitPublicInputs +/// +/// This call constructs an ast token referencing the above types +/// The name is set in the function above `transform`, hence the +/// whole token name is passed in +/// +/// The replaced code: +/// ```noir +/// +/// /// Before +/// fn foo() -> abi::PrivateCircuitPublicInputs { +/// // ... +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() { +/// // ... +/// } +fn create_return_type(ty: &str) -> FunctionReturnType { + let return_path = chained_path!("aztec", "abi", ty); + + let ty = make_type(UnresolvedTypeData::Named(return_path, vec![])); + FunctionReturnType::Ty(ty) +} + +/// Create Context Finish +/// +/// Each aztec function calls `context.finish()` at the end of a function +/// to return values required by the kernel. +/// +/// The replaced code: +/// ```noir +/// /// Before +/// fn foo() -> abi::PrivateCircuitPublicInputs { +/// // ... +/// context.finish() +/// } +/// +/// /// After +/// #[aztec(private)] +/// fn foo() { +/// // ... +/// } +fn create_context_finish() -> Statement { + let method_call = method_call( + variable("context"), // variable + "finish", // method name + vec![], // args + ); + make_statement(StatementKind::Expression(method_call)) +} + +// +// Methods to create hasher inputs +// + +fn add_struct_to_hasher(identifier: &Ident) -> Statement { + // If this is a struct, we call serialize and add the array to the hasher + let serialized_call = method_call( + variable_path(path(identifier.clone())), // variable + "serialize", // method name + vec![], // args + ); + + make_statement(StatementKind::Semi(method_call( + variable("hasher"), // variable + "add_multiple", // method name + vec![serialized_call], // args + ))) +} + +fn create_loop_over(var: Expression, loop_body: Vec) -> Statement { + // If this is an array of primitive types (integers / fields) we can add them each to the hasher + // casted to a field + let span = var.span; + + // `array.len()` + let end_range_expression = method_call( + var, // variable + "len", // method name + vec![], // args + ); + + // What will be looped over + // - `hasher.add({ident}[i] as Field)` + let for_loop_block = expression(ExpressionKind::Block(BlockExpression(loop_body))); + + // `for i in 0..{ident}.len()` + make_statement(StatementKind::For(ForLoopStatement { + range: ForRange::Range( + expression(ExpressionKind::Literal(Literal::Integer( + FieldElement::from(i128::from(0)), + false, + ))), + end_range_expression, + ), + identifier: ident("i"), + block: for_loop_block, + span, + })) +} + +fn add_array_to_hasher(identifier: &Ident, arr_type: &UnresolvedType) -> Statement { + // If this is an array of primitive types (integers / fields) we can add them each to the hasher + // casted to a field + + // Wrap in the semi thing - does that mean ended with semi colon? + // `hasher.add({ident}[i] as Field)` + + let arr_index = index_array(identifier.clone(), "i"); + let (add_expression, hasher_method_name) = match arr_type.typ { + UnresolvedTypeData::Named(..) => { + let hasher_method_name = "add_multiple".to_owned(); + let call = method_call( + // All serialise on each element + arr_index, // variable + "serialize", // method name + vec![], // args + ); + (call, hasher_method_name) + } + _ => { + let hasher_method_name = "add".to_owned(); + let call = cast( + arr_index, // lhs - `ident[i]` + UnresolvedTypeData::FieldElement, // cast to - `as Field` + ); + (call, hasher_method_name) + } + }; + + let block_statement = make_statement(StatementKind::Semi(method_call( + variable("hasher"), // variable + &hasher_method_name, // method name + vec![add_expression], + ))); + + create_loop_over(variable_ident(identifier.clone()), vec![block_statement]) +} + +fn add_field_to_hasher(identifier: &Ident) -> Statement { + // `hasher.add({ident})` + let ident = variable_path(path(identifier.clone())); + make_statement(StatementKind::Semi(method_call( + variable("hasher"), // variable + "add", // method name + vec![ident], // args + ))) +} + +fn add_cast_to_hasher(identifier: &Ident) -> Statement { + // `hasher.add({ident} as Field)` + // `{ident} as Field` + let cast_operation = cast( + variable_path(path(identifier.clone())), // lhs + UnresolvedTypeData::FieldElement, // rhs + ); + + // `hasher.add({ident} as Field)` + make_statement(StatementKind::Semi(method_call( + variable("hasher"), // variable + "add", // method name + vec![cast_operation], // args + ))) +} + +/// Computes the aztec signature for a resolved type. +fn signature_of_type(typ: &Type) -> String { + match typ { + Type::Integer(Signedness::Signed, bit_size) => format!("i{}", bit_size), + Type::Integer(Signedness::Unsigned, bit_size) => format!("u{}", bit_size), + Type::FieldElement => "Field".to_owned(), + Type::Bool => "bool".to_owned(), + Type::Array(len, typ) => { + if let Type::Constant(len) = **len { + format!("[{};{len}]", signature_of_type(typ)) + } else { + unimplemented!("Cannot generate signature for array with length type {:?}", typ) + } + } + Type::Struct(def, args) => { + let fields = def.borrow().get_fields(args); + let fields = vecmap(fields, |(_, typ)| signature_of_type(&typ)); + format!("({})", fields.join(",")) + } + Type::Tuple(types) => { + let fields = vecmap(types, signature_of_type); + format!("({})", fields.join(",")) + } + _ => unimplemented!("Cannot generate signature for type {:?}", typ), + } +} + +/// Computes the signature for a resolved event type. +/// It has the form 'EventName(Field,(Field),[u8;2])' +fn event_signature(event: &StructType) -> String { + let fields = vecmap(event.get_fields(&[]), |(_, typ)| signature_of_type(&typ)); + format!("{}({})", event.name.0.contents, fields.join(",")) +} diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000000..bf672ac0ad --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -eu + +cd $(dirname "$0") + +CMD=${1:-} + +if [ -n "$CMD" ]; then + if [ "$CMD" = "clean" ]; then + git clean -fdx + exit 0 + else + echo "Unknown command: $CMD" + exit 1 + fi +fi + +./scripts/bootstrap_native.sh +./scripts/bootstrap_packages.sh \ No newline at end of file diff --git a/compiler/fm/Cargo.toml b/compiler/fm/Cargo.toml index 9e4309693e..699f709e9b 100644 --- a/compiler/fm/Cargo.toml +++ b/compiler/fm/Cargo.toml @@ -9,7 +9,6 @@ license.workspace = true [dependencies] codespan-reporting.workspace = true -rust-embed = "6.6.0" serde.workspace = true [dev-dependencies] diff --git a/compiler/fm/src/file_map.rs b/compiler/fm/src/file_map.rs index 199723a28b..0cbdc535e4 100644 --- a/compiler/fm/src/file_map.rs +++ b/compiler/fm/src/file_map.rs @@ -1,11 +1,12 @@ use codespan_reporting::files::{Error, Files, SimpleFile, SimpleFiles}; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; use std::{ops::Range, path::PathBuf}; // XXX: File and FileMap serve as opaque types, so that the rest of the library does not need to import the dependency // or worry about when we change the dep -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct PathString(PathBuf); impl std::fmt::Display for PathString { @@ -30,7 +31,10 @@ impl From<&PathBuf> for PathString { } } #[derive(Debug)] -pub struct FileMap(SimpleFiles); +pub struct FileMap { + files: SimpleFiles, + name_to_id: HashMap, +} // XXX: Note that we derive Default here due to ModuleOrigin requiring us to set a FileId #[derive( @@ -59,17 +63,22 @@ impl<'input> File<'input> { impl FileMap { pub fn add_file(&mut self, file_name: PathString, code: String) -> FileId { - let file_id = self.0.add(file_name, code); - FileId(file_id) + let file_id = FileId(self.files.add(file_name.clone(), code)); + self.name_to_id.insert(file_name, file_id); + file_id } + pub fn get_file(&self, file_id: FileId) -> Option { - self.0.get(file_id.0).map(File).ok() + self.files.get(file_id.0).map(File).ok() } -} + pub fn get_file_id(&self, file_name: &PathString) -> Option { + self.name_to_id.get(file_name).cloned() + } +} impl Default for FileMap { fn default() -> Self { - FileMap(SimpleFiles::new()) + FileMap { files: SimpleFiles::new(), name_to_id: HashMap::new() } } } @@ -79,18 +88,18 @@ impl<'a> Files<'a> for FileMap { type Source = &'a str; fn name(&self, file_id: Self::FileId) -> Result { - Ok(self.0.get(file_id.as_usize())?.name().clone()) + Ok(self.files.get(file_id.as_usize())?.name().clone()) } fn source(&'a self, file_id: Self::FileId) -> Result { - Ok(self.0.get(file_id.as_usize())?.source().as_ref()) + Ok(self.files.get(file_id.as_usize())?.source().as_ref()) } fn line_index(&self, file_id: Self::FileId, byte_index: usize) -> Result { - self.0.get(file_id.as_usize())?.line_index((), byte_index) + self.files.get(file_id.as_usize())?.line_index((), byte_index) } fn line_range(&self, file_id: Self::FileId, line_index: usize) -> Result, Error> { - self.0.get(file_id.as_usize())?.line_range((), line_index) + self.files.get(file_id.as_usize())?.line_range((), line_index) } } diff --git a/compiler/fm/src/file_reader.rs b/compiler/fm/src/file_reader.rs deleted file mode 100644 index d17aefeda7..0000000000 --- a/compiler/fm/src/file_reader.rs +++ /dev/null @@ -1,49 +0,0 @@ -use rust_embed::RustEmbed; -use std::io::{Error, ErrorKind}; -use std::path::Path; - -// Based on the environment, we either read files using the rust standard library or we -// read files using the javascript host function - -pub type FileReader = dyn Fn(&Path) -> std::io::Result + Send; - -#[derive(RustEmbed)] -#[folder = "../../noir_stdlib/src"] -#[cfg_attr(not(target_os = "windows"), prefix = "std/")] -#[cfg_attr(target_os = "windows", prefix = r"std\")] // Note reversed slash direction -struct StdLibAssets; - -#[cfg(target_os = "windows")] -pub(super) fn is_stdlib_asset(path: &Path) -> bool { - path.starts_with("std\\") -} - -#[cfg(not(target_os = "windows"))] -pub(super) fn is_stdlib_asset(path: &Path) -> bool { - path.starts_with("std/") -} - -fn get_stdlib_asset(path: &Path) -> std::io::Result { - if !is_stdlib_asset(path) { - return Err(Error::new(ErrorKind::InvalidInput, "requested a non-stdlib asset")); - } - - match StdLibAssets::get(path.to_str().unwrap()) { - Some(std_lib_asset) => { - Ok(std::str::from_utf8(std_lib_asset.data.as_ref()).unwrap().to_string()) - } - - None => Err(Error::new(ErrorKind::NotFound, "invalid stdlib path")), - } -} - -pub(crate) fn read_file_to_string( - path_to_file: &Path, - get_non_stdlib_asset: &impl Fn(&Path) -> std::io::Result, -) -> std::io::Result { - if is_stdlib_asset(path_to_file) { - get_stdlib_asset(path_to_file) - } else { - get_non_stdlib_asset(path_to_file) - } -} diff --git a/compiler/fm/src/lib.rs b/compiler/fm/src/lib.rs index 6e11489f7f..2a54e58d3b 100644 --- a/compiler/fm/src/lib.rs +++ b/compiler/fm/src/lib.rs @@ -4,11 +4,11 @@ #![warn(clippy::semicolon_if_nothing_returned)] mod file_map; -mod file_reader; pub use file_map::{File, FileId, FileMap, PathString}; -use file_reader::is_stdlib_asset; -pub use file_reader::FileReader; + +// Re-export for the lsp +pub use codespan_reporting::files as codespan_files; use std::{ collections::HashMap, @@ -19,10 +19,9 @@ pub const FILE_EXTENSION: &str = "nr"; pub struct FileManager { root: PathBuf, - file_map: file_map::FileMap, + file_map: FileMap, id_to_path: HashMap, path_to_id: HashMap, - file_reader: Box, } impl std::fmt::Debug for FileManager { @@ -37,13 +36,12 @@ impl std::fmt::Debug for FileManager { } impl FileManager { - pub fn new(root: &Path, file_reader: Box) -> Self { + pub fn new(root: &Path) -> Self { Self { root: root.normalize(), file_map: Default::default(), id_to_path: Default::default(), path_to_id: Default::default(), - file_reader, } } @@ -51,25 +49,32 @@ impl FileManager { &self.file_map } - pub fn add_file(&mut self, file_name: &Path) -> Option { - // Handle both relative file paths and std/lib virtual paths. - let resolved_path: PathBuf = if is_stdlib_asset(file_name) { - // Special case for stdlib where we want to read specifically the `std/` relative path - // TODO: The stdlib path should probably be an absolute path rooted in something people would never create - file_name.to_path_buf() - } else { - self.root.join(file_name).normalize() - }; + /// Adds a source file to the [`FileManager`]. + /// + /// The `file_name` is expected to be relative to the [`FileManager`]'s root directory. + pub fn add_file_with_source(&mut self, file_name: &Path, source: String) -> Option { + let file_name = self.root.join(file_name); + self.add_file_with_source_canonical_path(&file_name, source) + } - // Check that the resolved path already exists in the file map, if it is, we return it. - if let Some(file_id) = self.path_to_id.get(&resolved_path) { + /// Adds a source file to the [`FileManager`] using a path which is not appended to the root path. + /// + /// This should only be used for the stdlib as these files do not exist on the user's filesystem. + pub fn add_file_with_source_canonical_path( + &mut self, + file_name: &Path, + source: String, + ) -> Option { + let file_name = file_name.normalize(); + // Check that the file name already exists in the file map, if it is, we return it. + if let Some(file_id) = self.path_to_id.get(&file_name) { return Some(*file_id); } + let file_name_path_buf = file_name.to_path_buf(); // Otherwise we add the file - let source = file_reader::read_file_to_string(&resolved_path, &self.file_reader).ok()?; - let file_id = self.file_map.add_file(resolved_path.clone().into(), source); - self.register_path(file_id, resolved_path); + let file_id = self.file_map.add_file(file_name_path_buf.clone().into(), source); + self.register_path(file_id, file_name_path_buf); Some(file_id) } @@ -94,7 +99,10 @@ impl FileManager { self.id_to_path.get(&file_id).unwrap().as_path() } - pub fn find_module(&mut self, anchor: FileId, mod_name: &str) -> Result { + // TODO: This should also ideally not be here, so that the file manager + // TODO: does not know about rust modules. + // TODO: Ideally this is moved to def_collector_mod and we make this method accept a FileManager + pub fn find_module(&self, anchor: FileId, mod_name: &str) -> Result { let anchor_path = self.path(anchor).with_extension(""); let anchor_dir = anchor_path.parent().unwrap(); @@ -107,10 +115,19 @@ impl FileManager { anchor_path.join(format!("{mod_name}.{FILE_EXTENSION}")) }; - self.add_file(&candidate).ok_or_else(|| candidate.as_os_str().to_string_lossy().to_string()) + self.name_to_id(candidate.clone()) + .ok_or_else(|| candidate.as_os_str().to_string_lossy().to_string()) + } + + // 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)) } } +// TODO: This should not be here because the file manager should not know about the +// TODO: rust modules. See comment on `find_module`` +// TODO: Moreover, the check for main, lib, mod should ideally not be done here /// Returns true if a module's child module's are expected to be in the same directory. /// Returns false if they are expected to be in a subdirectory matching the name of the module. fn should_check_siblings_for_module(module_path: &Path, parent_path: &Path) -> bool { @@ -212,9 +229,11 @@ mod tests { use super::*; use tempfile::{tempdir, TempDir}; - fn create_dummy_file(dir: &TempDir, file_name: &Path) { + // Returns the absolute path to the file + fn create_dummy_file(dir: &TempDir, file_name: &Path) -> PathBuf { let file_path = dir.path().join(file_name); - let _file = std::fs::File::create(file_path).unwrap(); + let _file = std::fs::File::create(&file_path).unwrap(); + file_path } #[test] @@ -224,9 +243,9 @@ mod tests { let entry_file_name = Path::new("my_dummy_file.nr"); create_dummy_file(&dir, entry_file_name); - let mut fm = FileManager::new(dir.path(), Box::new(|path| std::fs::read_to_string(path))); + let mut fm = FileManager::new(dir.path()); - let file_id = fm.add_file(entry_file_name).unwrap(); + let file_id = fm.add_file_with_source(entry_file_name, "fn foo() {}".to_string()).unwrap(); let dep_file_name = Path::new("foo.nr"); create_dummy_file(&dir, dep_file_name); @@ -239,9 +258,9 @@ mod tests { let file_name = Path::new("foo.nr"); create_dummy_file(&dir, file_name); - let mut fm = FileManager::new(dir.path(), Box::new(|path| std::fs::read_to_string(path))); + let mut fm = FileManager::new(dir.path()); - let file_id = fm.add_file(file_name).unwrap(); + let file_id = fm.add_file_with_source(file_name, "fn foo() {}".to_string()).unwrap(); assert!(fm.path(file_id).ends_with("foo.nr")); } @@ -249,14 +268,14 @@ mod tests { #[test] fn path_resolve_sub_module() { let dir = tempdir().unwrap(); - let mut fm = FileManager::new(dir.path(), Box::new(|path| std::fs::read_to_string(path))); + let mut fm = FileManager::new(dir.path()); // Create a lib.nr file at the root. // we now have dir/lib.nr - let file_name = Path::new("lib.nr"); - create_dummy_file(&dir, file_name); - - let file_id = fm.add_file(file_name).unwrap(); + let lib_nr_path = create_dummy_file(&dir, Path::new("lib.nr")); + let file_id = fm + .add_file_with_source(lib_nr_path.as_path(), "fn foo() {}".to_string()) + .expect("could not add file to file manager and obtain a FileId"); // Create a sub directory // we now have: @@ -269,14 +288,16 @@ mod tests { // we no have: // - dir/lib.nr // - dir/sub_dir/foo.nr - create_dummy_file(&sub_dir, Path::new("foo.nr")); + let foo_nr_path = create_dummy_file(&sub_dir, Path::new("foo.nr")); + fm.add_file_with_source(foo_nr_path.as_path(), "fn foo() {}".to_string()); // Add a parent module for the sub_dir // we no have: // - dir/lib.nr // - dir/sub_dir.nr // - dir/sub_dir/foo.nr - create_dummy_file(&dir, Path::new(&format!("{sub_dir_name}.nr"))); + let sub_dir_nr_path = create_dummy_file(&dir, Path::new(&format!("{sub_dir_name}.nr"))); + fm.add_file_with_source(sub_dir_nr_path.as_path(), "fn foo() {}".to_string()); // First check for the sub_dir.nr file and add it to the FileManager let sub_dir_file_id = fm.find_module(file_id, sub_dir_name).unwrap(); @@ -295,7 +316,7 @@ mod tests { let sub_dir = TempDir::new_in(&dir).unwrap(); let sub_sub_dir = TempDir::new_in(&sub_dir).unwrap(); - let mut fm = FileManager::new(dir.path(), Box::new(|path| std::fs::read_to_string(path))); + let mut fm = FileManager::new(dir.path()); // Create a lib.nr file at the root. let file_name = Path::new("lib.nr"); @@ -305,8 +326,9 @@ mod tests { let second_file_name = PathBuf::from(sub_sub_dir.path()).join("./../../lib.nr"); // Add both files to the file manager - let file_id = fm.add_file(file_name).unwrap(); - let second_file_id = fm.add_file(&second_file_name).unwrap(); + let file_id = fm.add_file_with_source(file_name, "fn foo() {}".to_string()).unwrap(); + let second_file_id = + fm.add_file_with_source(&second_file_name, "fn foo() {}".to_string()).unwrap(); assert_eq!(file_id, second_file_id); } diff --git a/compiler/integration-tests/circuits/main/Nargo.toml b/compiler/integration-tests/circuits/main/Nargo.toml deleted file mode 100644 index cc5a0a357f..0000000000 --- a/compiler/integration-tests/circuits/main/Nargo.toml +++ /dev/null @@ -1,5 +0,0 @@ -[package] -name = "main" -type = "bin" -authors = [""] -[dependencies] diff --git a/compiler/integration-tests/circuits/recursion/src/main.nr b/compiler/integration-tests/circuits/recursion/src/main.nr index 7cf956d195..e60e4e0b61 100644 --- a/compiler/integration-tests/circuits/recursion/src/main.nr +++ b/compiler/integration-tests/circuits/recursion/src/main.nr @@ -1,14 +1,17 @@ use dep::std; fn main( - verification_key: [Field; 114], - proof: [Field; 94], - public_inputs: [Field; 1], - key_hash: Field, - input_aggregation_object: [Field; 16] -) -> pub [Field; 16] { - let vk : [Field] = verification_key; - let p : [Field] = proof; - let pi : [Field] = public_inputs; - std::verify_proof(vk, p, pi, key_hash, input_aggregation_object) + verification_key : [Field; 114], + proof : [Field; 94], + public_inputs : [Field; 1], + key_hash : Field, +) -> pub [Field;16]{ + let input_aggregation_object = [0; 16]; + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash, + input_aggregation_object + ) } diff --git a/compiler/integration-tests/hardhat.config.ts b/compiler/integration-tests/hardhat.config.ts index 2c68b3fae0..af4728c68e 100644 --- a/compiler/integration-tests/hardhat.config.ts +++ b/compiler/integration-tests/hardhat.config.ts @@ -12,6 +12,9 @@ const config: HardhatUserConfig = { }, }, }, + mocha: { + timeout: 5 * 60 * 1000, + }, }; export default config; diff --git a/compiler/integration-tests/package.json b/compiler/integration-tests/package.json index 344d136126..c4e424df48 100644 --- a/compiler/integration-tests/package.json +++ b/compiler/integration-tests/package.json @@ -16,7 +16,6 @@ "@noir-lang/backend_barretenberg": "workspace:*", "@noir-lang/noir_js": "workspace:*", "@noir-lang/noir_wasm": "workspace:*", - "@noir-lang/source-resolver": "workspace:*", "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", "@nomicfoundation/hardhat-ethers": "^3.0.0", "@web/dev-server-esbuild": "^0.3.6", diff --git a/compiler/integration-tests/scripts/codegen-verifiers.sh b/compiler/integration-tests/scripts/codegen-verifiers.sh index d9d9d4f243..b3a5221727 100644 --- a/compiler/integration-tests/scripts/codegen-verifiers.sh +++ b/compiler/integration-tests/scripts/codegen-verifiers.sh @@ -5,16 +5,22 @@ self_path=$(dirname "$(readlink -f "$0")") repo_root=$self_path/../../.. # Run codegen-verifier for 1_mul -mul_dir=$repo_root/tooling/nargo_cli/tests/execution_success/1_mul +mul_dir=$repo_root/test_programs/execution_success/1_mul nargo --program-dir $mul_dir codegen-verifier -# Run codegen-verifier for main -main_dir=$repo_root/compiler/integration-tests/circuits/main -nargo --program-dir $main_dir codegen-verifier +# Run codegen-verifier for assert_statement +assert_statement_dir=$repo_root/test_programs/execution_success/assert_statement +nargo --program-dir $assert_statement_dir codegen-verifier + +# Run codegen-verifier for recursion +recursion_dir=$repo_root/compiler/integration-tests/circuits/recursion +nargo --program-dir $recursion_dir codegen-verifier # Copy compiled contracts from the root of compiler/integration-tests contracts_dir=$self_path/../contracts +rm -rf $contracts_dir mkdir $contracts_dir cp $mul_dir/contract/1_mul/plonk_vk.sol $contracts_dir/1_mul.sol -cp $main_dir/contract/main/plonk_vk.sol $contracts_dir/main.sol +cp $assert_statement_dir/contract/assert_statement/plonk_vk.sol $contracts_dir/assert_statement.sol +cp $recursion_dir/contract/recursion/plonk_vk.sol $contracts_dir/recursion.sol 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 95a1aa502a..29e2fbc55b 100644 --- a/compiler/integration-tests/test/browser/compile_prove_verify.test.ts +++ b/compiler/integration-tests/test/browser/compile_prove_verify.test.ts @@ -1,17 +1,17 @@ import { expect } from '@esm-bundle/chai'; -import { Logger } from 'tslog'; import * as TOML from 'smol-toml'; -import { initializeResolver } from '@noir-lang/source-resolver'; -import newCompiler, { CompiledProgram, compile, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm'; +import newCompiler, { + CompiledProgram, + PathToFileSourceMap, + compile, + init_log_level as compilerLogLevel, +} 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 { getFile } from './utils.js'; -import { TEST_LOG_LEVEL } from '../environment.js'; - -const logger = new Logger({ name: 'test', minLevel: TEST_LOG_LEVEL }); await newCompiler(); @@ -19,11 +19,11 @@ compilerLogLevel('INFO'); const test_cases = [ { - case: 'tooling/nargo_cli/tests/execution_success/1_mul', + case: 'test_programs/execution_success/1_mul', numPublicInputs: 0, }, { - case: 'compiler/integration-tests/circuits/main', + case: 'test_programs/execution_success/assert_statement', numPublicInputs: 1, }, ]; @@ -33,14 +33,11 @@ const suite = Mocha.Suite.create(mocha.suite, 'Noir end to end test'); suite.timeout(60 * 20e3); //20mins function getCircuit(noirSource: string): CompiledProgram { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - initializeResolver((id: string) => { - logger.debug('source-resolver: resolving:', id); - return noirSource; - }); + const sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code('main.nr', noirSource); // We're ignoring this in the resolver but pass in something sensible. - const result = compile('/main.nr'); + const result = compile('main.nr', undefined, undefined, sourceMap); if (!('program' in result)) { throw new Error('Compilation failed'); } diff --git a/compiler/integration-tests/test/browser/recursion.test.ts b/compiler/integration-tests/test/browser/recursion.test.ts index dbf7488265..faa317b2c3 100644 --- a/compiler/integration-tests/test/browser/recursion.test.ts +++ b/compiler/integration-tests/test/browser/recursion.test.ts @@ -2,8 +2,12 @@ import { expect } from '@esm-bundle/chai'; import { TEST_LOG_LEVEL } from '../environment.js'; import { Logger } from 'tslog'; -import { initializeResolver } from '@noir-lang/source-resolver'; -import newCompiler, { CompiledProgram, compile, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm'; +import newCompiler, { + CompiledProgram, + PathToFileSourceMap, + compile, + init_log_level as compilerLogLevel, +} from '@noir-lang/noir_wasm'; import { acvm, abi, Noir } from '@noir-lang/noir_js'; import * as TOML from 'smol-toml'; @@ -23,18 +27,13 @@ await initACVM(); compilerLogLevel('INFO'); const base_relative_path = '../../../../..'; -const circuit_main = 'compiler/integration-tests/circuits/main'; +const circuit_main = 'test_programs/execution_success/assert_statement'; const circuit_recursion = 'compiler/integration-tests/circuits/recursion'; function getCircuit(noirSource: string): CompiledProgram { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - initializeResolver((id: string) => { - logger.debug('source-resolver: resolving:', id); - return noirSource; - }); - - // We're ignoring this in the resolver but pass in something sensible. - const result = compile('/main.nr'); + const sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code('main.nr', noirSource); + const result = compile('main.nr', undefined, undefined, sourceMap); if (!('program' in result)) { throw new Error('Compilation failed'); } diff --git a/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts new file mode 100644 index 0000000000..6c20d44882 --- /dev/null +++ b/compiler/integration-tests/test/node/onchain_recursive_verification.test.ts @@ -0,0 +1,80 @@ +import { expect } from 'chai'; +import { ethers } from 'hardhat'; + +import { readFileSync } from 'node:fs'; +import { resolve } from 'path'; +import toml from 'toml'; + +import { + compile, + CompiledProgram, + init_log_level as compilerLogLevel, + PathToFileSourceMap, +} from '@noir-lang/noir_wasm'; +import { Noir } from '@noir-lang/noir_js'; +import { BarretenbergBackend, flattenPublicInputs } from '@noir-lang/backend_barretenberg'; +import { Field, InputMap } from '@noir-lang/noirc_abi'; + +compilerLogLevel('INFO'); + +it(`smart contract can verify a recursive proof`, async () => { + const innerSourcePath = resolve(`../../test_programs/execution_success/assert_statement/src/main.nr`); + const sourceMapInnerProgram = new PathToFileSourceMap(); + sourceMapInnerProgram.add_source_code(innerSourcePath, readFileSync(innerSourcePath, 'utf-8')); + const innerProgram = ( + compile(innerSourcePath, undefined, undefined, sourceMapInnerProgram) as { program: CompiledProgram } + ).program; + + const recursionSourcePath = resolve(`./circuits/recursion/src/main.nr`); + const sourceMapRecursionProgram = new PathToFileSourceMap(); + sourceMapRecursionProgram.add_source_code(recursionSourcePath, readFileSync(recursionSourcePath, 'utf-8')); + const recursionProgram = ( + compile(recursionSourcePath, undefined, undefined, sourceMapRecursionProgram) as { program: CompiledProgram } + ).program; + + // Intermediate proof + + const inner_backend = new BarretenbergBackend(innerProgram); + const inner = new Noir(innerProgram); + + const inner_prover_toml = readFileSync( + resolve(`../../test_programs/execution_success/assert_statement/Prover.toml`), + ).toString(); + const inner_inputs = toml.parse(inner_prover_toml); + + const { witness: main_witness } = await inner.execute(inner_inputs); + const intermediate_proof = await inner_backend.generateIntermediateProof(main_witness); + + expect(await inner_backend.verifyIntermediateProof(intermediate_proof)).to.be.true; + + const { proofAsFields, vkAsFields, vkHash } = await inner_backend.generateIntermediateProofArtifacts( + intermediate_proof, + 1, // 1 public input + ); + + // Final proof + + const recursion_backend = new BarretenbergBackend(recursionProgram); + const recursion = new Noir(recursionProgram, recursion_backend); + + const recursion_inputs: InputMap = { + verification_key: vkAsFields, + proof: proofAsFields, + public_inputs: [inner_inputs.y as Field], + key_hash: vkHash, + }; + + const recursion_proof = await recursion.generateFinalProof(recursion_inputs); + expect(await recursion.verifyFinalProof(recursion_proof)).to.be.true; + + // Smart contract verification + + const contract = await ethers.deployContract('contracts/recursion.sol:UltraVerifier', []); + + const result = await contract.verify.staticCall( + recursion_proof.proof, + flattenPublicInputs(recursion_proof.publicInputs), + ); + + expect(result).to.be.true; +}); 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 738bc2df8d..5b3d0e2d33 100644 --- a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts +++ b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts @@ -5,21 +5,21 @@ import { readFileSync } from 'node:fs'; import { resolve } from 'path'; import toml from 'toml'; -import { compile, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm'; +import { PathToFileSourceMap, compile, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm'; import { Noir } from '@noir-lang/noir_js'; -import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { BarretenbergBackend, flattenPublicInputs } from '@noir-lang/backend_barretenberg'; compilerLogLevel('INFO'); const test_cases = [ { - case: 'tooling/nargo_cli/tests/execution_success/1_mul', + case: 'test_programs/execution_success/1_mul', compiled: 'contracts/1_mul.sol:UltraVerifier', numPublicInputs: 0, }, { - case: 'compiler/integration-tests/circuits/main', - compiled: 'contracts/main.sol:UltraVerifier', + case: 'test_programs/execution_success/assert_statement', + compiled: 'contracts/assert_statement.sol:UltraVerifier', numPublicInputs: 1, }, ]; @@ -31,9 +31,11 @@ test_cases.forEach((testInfo) => { const base_relative_path = '../..'; const test_case = testInfo.case; - const noir_source_path = resolve(`${base_relative_path}/${test_case}/src/main.nr`); + const noirSourcePath = resolve(`${base_relative_path}/${test_case}/src/main.nr`); + const sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code(noirSourcePath, readFileSync(noirSourcePath, 'utf-8')); - const compileResult = compile(noir_source_path); + const compileResult = compile(noirSourcePath, undefined, undefined, sourceMap); if (!('program' in compileResult)) { throw new Error('Compilation failed'); } @@ -57,9 +59,9 @@ test_cases.forEach((testInfo) => { // Smart contract verification - const contract = await ethers.deployContract(testInfo.compiled, [], {}); + const contract = await ethers.deployContract(testInfo.compiled, []); - const result = await contract.verify(proofData.proof, proofData.publicInputs); + const result = await contract.verify(proofData.proof, flattenPublicInputs(proofData.publicInputs)); expect(result).to.be.true; }); diff --git a/compiler/noirc_driver/Cargo.toml b/compiler/noirc_driver/Cargo.toml index 09044b3932..e5a837e682 100644 --- a/compiler/noirc_driver/Cargo.toml +++ b/compiler/noirc_driver/Cargo.toml @@ -21,3 +21,6 @@ iter-extended.workspace = true fm.workspace = true serde.workspace = true fxhash.workspace = true +rust-embed = "6.6.0" + +aztec_macros = { path = "../../aztec_macros" } diff --git a/compiler/noirc_driver/src/abi_gen.rs b/compiler/noirc_driver/src/abi_gen.rs index a4835338f1..9d0d64b630 100644 --- a/compiler/noirc_driver/src/abi_gen.rs +++ b/compiler/noirc_driver/src/abi_gen.rs @@ -2,11 +2,12 @@ use std::collections::BTreeMap; use acvm::acir::native_types::Witness; use iter_extended::{btree_map, vecmap}; -use noirc_abi::{Abi, AbiParameter, AbiType}; +use noirc_abi::{Abi, AbiParameter, AbiReturnType, AbiType}; use noirc_frontend::{ hir::Context, hir_def::{function::Param, stmt::HirPattern}, node_interner::{FuncId, NodeInterner}, + Visibility, }; use std::ops::Range; @@ -17,9 +18,12 @@ pub(super) fn gen_abi( func_id: &FuncId, input_witnesses: Vec, return_witnesses: Vec, + return_visibility: Visibility, ) -> Abi { let (parameters, return_type) = compute_function_abi(context, func_id); let param_witnesses = param_witnesses_from_abi_param(¶meters, input_witnesses); + let return_type = return_type + .map(|typ| AbiReturnType { abi_type: typ, visibility: return_visibility.into() }); Abi { parameters, return_type, param_witnesses, return_witnesses } } @@ -119,7 +123,7 @@ mod test { let collapsed_witnesses = collapse_ranges(&witnesses); - assert_eq!(collapsed_witnesses, vec![Range { start: Witness(1), end: Witness(4) },]) + assert_eq!(collapsed_witnesses, vec![Range { start: Witness(1), end: Witness(4) },]); } #[test] @@ -136,6 +140,6 @@ mod test { Range { start: Witness(5), end: Witness(7) }, Range { start: Witness(2), end: Witness(5) } ] - ) + ); } } diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index 456c2c4960..c326d04c84 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -13,6 +13,7 @@ use noirc_evaluator::errors::RuntimeError; use noirc_frontend::graph::{CrateId, CrateName}; use noirc_frontend::hir::def_map::{Contract, CrateDefMap}; use noirc_frontend::hir::Context; +use noirc_frontend::macros_api::MacroProcessor; use noirc_frontend::monomorphization::monomorphize; use noirc_frontend::node_interner::FuncId; use serde::{Deserialize, Serialize}; @@ -22,6 +23,7 @@ mod abi_gen; mod contract; mod debug; mod program; +mod stdlib; use debug::filter_relevant_files; @@ -60,6 +62,14 @@ pub struct CompileOptions { /// Suppress warnings #[arg(long, conflicts_with = "deny_warnings")] pub silence_warnings: bool, + + /// Output ACIR gzipped bytecode instead of the JSON artefact + #[arg(long, hide = true)] + pub only_acir: bool, + + /// Disables the builtin macros being used in the compiler + #[arg(long, hide = true)] + pub disable_macros: bool, } /// Helper type used to signify where only warnings are expected in file diagnostics @@ -73,11 +83,23 @@ pub type CompilationResult = Result<(T, Warnings), ErrorsAndWarnings>; /// Adds the file from the file system at `Path` to the crate graph as a root file pub fn prepare_crate(context: &mut Context, file_name: &Path) -> CrateId { + // Add the stdlib contents to the file manager, since every package automatically has a dependency + // on the stdlib. For other dependencies, we read the package.Dependencies file to add their file + // contents to the file manager. However since the dependency on the stdlib is implicit, we need + // to manually add it here. + let stdlib_paths_with_source = stdlib::stdlib_paths_with_source(); + for (path, source) in stdlib_paths_with_source { + context.file_manager.add_file_with_source_canonical_path(Path::new(&path), source); + } + let path_to_std_lib_file = Path::new(STD_CRATE_NAME).join("lib.nr"); - let std_file_id = context.file_manager.add_file(&path_to_std_lib_file).unwrap(); + let std_file_id = context + .file_manager + .name_to_id(path_to_std_lib_file) + .expect("stdlib file id is expected to be present"); let std_crate_id = context.crate_graph.add_stdlib(std_file_id); - let root_file_id = context.file_manager.add_file(file_name).unwrap(); + let root_file_id = context.file_manager.name_to_id(file_name.to_path_buf()).unwrap_or_else(|| panic!("files are expected to be added to the FileManager before reaching the compiler file_path: {file_name:?}")); let root_crate_id = context.crate_graph.add_crate_root(root_file_id); @@ -88,7 +110,10 @@ pub fn prepare_crate(context: &mut Context, file_name: &Path) -> CrateId { // Adds the file from the file system at `Path` to the crate graph pub fn prepare_dependency(context: &mut Context, file_name: &Path) -> CrateId { - let root_file_id = context.file_manager.add_file(file_name).unwrap(); + let root_file_id = context + .file_manager + .name_to_id(file_name.to_path_buf()) + .unwrap_or_else(|| panic!("files are expected to be added to the FileManager before reaching the compiler file_path: {file_name:?}")); let crate_id = context.crate_graph.add_crate(root_file_id); @@ -120,9 +145,16 @@ pub fn check_crate( context: &mut Context, crate_id: CrateId, deny_warnings: bool, + disable_macros: bool, ) -> CompilationResult<()> { + let macros: Vec<&dyn MacroProcessor> = if disable_macros { + vec![] + } else { + vec![&aztec_macros::AztecMacro as &dyn MacroProcessor] + }; + let mut errors = vec![]; - let diagnostics = CrateDefMap::collect_defs(crate_id, context); + let diagnostics = CrateDefMap::collect_defs(crate_id, context, macros); errors.extend(diagnostics.into_iter().map(|(error, file_id)| { let diagnostic: CustomDiagnostic = error.into(); diagnostic.in_file(file_id) @@ -155,7 +187,8 @@ pub fn compile_main( cached_program: Option, force_compile: bool, ) -> CompilationResult { - let (_, mut warnings) = check_crate(context, crate_id, options.deny_warnings)?; + let (_, mut warnings) = + check_crate(context, crate_id, options.deny_warnings, options.disable_macros)?; let main = context.get_main_function(&crate_id).ok_or_else(|| { // TODO(#2155): This error might be a better to exist in Nargo @@ -188,7 +221,8 @@ pub fn compile_contract( crate_id: CrateId, options: &CompileOptions, ) -> CompilationResult { - let (_, warnings) = check_crate(context, crate_id, options.deny_warnings)?; + let (_, warnings) = + check_crate(context, crate_id, options.deny_warnings, options.disable_macros)?; // TODO: We probably want to error if contracts is empty let contracts = context.get_all_contracts(&crate_id); @@ -340,11 +374,12 @@ pub fn compile_no_check( if !force_compile && hashes_match { return Ok(cached_program.expect("cache must exist for hashes to match")); } - + let visibility = program.return_visibility; let (circuit, debug, input_witnesses, return_witnesses, warnings) = create_circuit(program, options.show_ssa, options.show_brillig)?; - let abi = abi_gen::gen_abi(context, &main_function, input_witnesses, return_witnesses); + let abi = + abi_gen::gen_abi(context, &main_function, input_witnesses, return_witnesses, visibility); let file_map = filter_relevant_files(&[debug.clone()], &context.file_manager); Ok(CompiledProgram { diff --git a/compiler/noirc_driver/src/stdlib.rs b/compiler/noirc_driver/src/stdlib.rs new file mode 100644 index 0000000000..5a91e3f45b --- /dev/null +++ b/compiler/noirc_driver/src/stdlib.rs @@ -0,0 +1,24 @@ +use rust_embed::RustEmbed; + +#[derive(RustEmbed)] +#[folder = "../../noir_stdlib/src"] +#[cfg_attr(not(target_os = "windows"), prefix = "std/")] +#[cfg_attr(target_os = "windows", prefix = r"std\")] // Note reversed slash direction +struct StdLibAssets; + +// Returns a vector of tuples containing the path to a stdlib file in the std lib crate +// along with the source code of that file. +// +// This is needed because when we preload the file manager, it needs to know where +// the source code for the stdlib is. The stdlib is treated special because it comes with +// the compiler and is never included as a dependency like other user defined crates. +pub(crate) fn stdlib_paths_with_source() -> Vec<(String, String)> { + StdLibAssets::iter() + .map(|path| { + let source = std::str::from_utf8(StdLibAssets::get(&path).unwrap().data.as_ref()) + .unwrap() + .to_string(); + (path.to_string(), source) + }) + .collect() +} diff --git a/compiler/noirc_errors/src/position.rs b/compiler/noirc_errors/src/position.rs index e308eb9a2c..007ec58ca2 100644 --- a/compiler/noirc_errors/src/position.rs +++ b/compiler/noirc_errors/src/position.rs @@ -65,6 +65,10 @@ impl Span { Span::inclusive(start, start) } + pub fn empty(position: u32) -> Span { + Span::from(position..position) + } + #[must_use] pub fn merge(self, other: Span) -> Span { Span(self.0.merge(other.0)) @@ -81,6 +85,16 @@ impl Span { pub fn end(&self) -> u32 { self.0.end().into() } + + pub fn contains(&self, other: &Span) -> bool { + self.start() <= other.start() && self.end() >= other.end() + } + + pub fn is_smaller(&self, other: &Span) -> bool { + let self_distance = self.end() - self.start(); + let other_distance = other.end() - other.start(); + self_distance < other_distance + } } impl From for Range { @@ -129,4 +143,8 @@ impl Location { pub fn dummy() -> Self { Self { span: Span::single_char(0), file: FileId::dummy() } } + + pub fn contains(&self, other: &Location) -> bool { + self.file == other.file && self.span.contains(&other.span) + } } 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 0d97dd1260..9979bf0cd2 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 @@ -1,9 +1,9 @@ -use acvm::acir::{ - brillig::{BlackBoxOp, HeapVector, RegisterOrMemory}, - BlackBoxFunc, -}; +use acvm::acir::{brillig::BlackBoxOp, BlackBoxFunc}; -use crate::brillig::brillig_ir::BrilligContext; +use crate::brillig::brillig_ir::{ + brillig_variable::{BrilligVariable, BrilligVector}, + BrilligContext, +}; /// Transforms SSA's black box function calls into the corresponding brillig instructions /// Extracting arguments and results from the SSA function call @@ -11,31 +11,31 @@ use crate::brillig::brillig_ir::BrilligContext; pub(crate) fn convert_black_box_call( brillig_context: &mut BrilligContext, bb_func: &BlackBoxFunc, - function_arguments: &[RegisterOrMemory], - function_results: &[RegisterOrMemory], + function_arguments: &[BrilligVariable], + function_results: &[BrilligVariable], ) { match bb_func { BlackBoxFunc::SHA256 => { - if let ([message], [RegisterOrMemory::HeapArray(result_array)]) = + if let ([message], [BrilligVariable::BrilligArray(result_array)]) = (function_arguments, function_results) { let message_vector = convert_array_or_vector(brillig_context, message, bb_func); brillig_context.black_box_op_instruction(BlackBoxOp::Sha256 { - message: message_vector, - output: *result_array, + message: message_vector.to_heap_vector(), + output: result_array.to_heap_array(), }); } else { unreachable!("ICE: SHA256 expects one array argument and one array result") } } BlackBoxFunc::Blake2s => { - if let ([message], [RegisterOrMemory::HeapArray(result_array)]) = + if let ([message], [BrilligVariable::BrilligArray(result_array)]) = (function_arguments, function_results) { let message_vector = convert_array_or_vector(brillig_context, message, bb_func); brillig_context.black_box_op_instruction(BlackBoxOp::Blake2s { - message: message_vector, - output: *result_array, + message: message_vector.to_heap_vector(), + output: result_array.to_heap_array(), }); } else { unreachable!("ICE: Blake2s expects one array argument and one array result") @@ -43,28 +43,28 @@ pub(crate) fn convert_black_box_call( } BlackBoxFunc::Keccak256 => { if let ( - [message, RegisterOrMemory::RegisterIndex(array_size)], - [RegisterOrMemory::HeapArray(result_array)], + [message, BrilligVariable::Simple(array_size)], + [BrilligVariable::BrilligArray(result_array)], ) = (function_arguments, function_results) { let mut message_vector = convert_array_or_vector(brillig_context, message, bb_func); message_vector.size = *array_size; brillig_context.black_box_op_instruction(BlackBoxOp::Keccak256 { - message: message_vector, - output: *result_array, + message: message_vector.to_heap_vector(), + output: result_array.to_heap_array(), }); } else { unreachable!("ICE: Keccak256 expects message, message size and result array") } } BlackBoxFunc::HashToField128Security => { - if let ([message], [RegisterOrMemory::RegisterIndex(result_register)]) = + if let ([message], [BrilligVariable::Simple(result_register)]) = (function_arguments, function_results) { let message_vector = convert_array_or_vector(brillig_context, message, bb_func); brillig_context.black_box_op_instruction(BlackBoxOp::HashToField128Security { - message: message_vector, + message: message_vector.to_heap_vector(), output: *result_register, }); } else { @@ -73,17 +73,17 @@ pub(crate) fn convert_black_box_call( } BlackBoxFunc::EcdsaSecp256k1 => { if let ( - [RegisterOrMemory::HeapArray(public_key_x), RegisterOrMemory::HeapArray(public_key_y), RegisterOrMemory::HeapArray(signature), message], - [RegisterOrMemory::RegisterIndex(result_register)], + [BrilligVariable::BrilligArray(public_key_x), BrilligVariable::BrilligArray(public_key_y), BrilligVariable::BrilligArray(signature), message], + [BrilligVariable::Simple(result_register)], ) = (function_arguments, function_results) { let message_hash_vector = convert_array_or_vector(brillig_context, message, bb_func); brillig_context.black_box_op_instruction(BlackBoxOp::EcdsaSecp256k1 { - hashed_msg: message_hash_vector, - public_key_x: *public_key_x, - public_key_y: *public_key_y, - signature: *signature, + hashed_msg: message_hash_vector.to_heap_vector(), + public_key_x: public_key_x.to_heap_array(), + public_key_y: public_key_y.to_heap_array(), + signature: signature.to_heap_array(), result: *result_register, }); } else { @@ -94,15 +94,15 @@ pub(crate) fn convert_black_box_call( } BlackBoxFunc::PedersenCommitment => { if let ( - [message, RegisterOrMemory::RegisterIndex(domain_separator)], - [RegisterOrMemory::HeapArray(result_array)], + [message, BrilligVariable::Simple(domain_separator)], + [BrilligVariable::BrilligArray(result_array)], ) = (function_arguments, function_results) { let message_vector = convert_array_or_vector(brillig_context, message, bb_func); brillig_context.black_box_op_instruction(BlackBoxOp::PedersenCommitment { - inputs: message_vector, + inputs: message_vector.to_heap_vector(), domain_separator: *domain_separator, - output: *result_array, + output: result_array.to_heap_array(), }); } else { unreachable!("ICE: Pedersen expects one array argument, a register for the domain separator, and one array result") @@ -110,13 +110,13 @@ pub(crate) fn convert_black_box_call( } BlackBoxFunc::PedersenHash => { if let ( - [message, RegisterOrMemory::RegisterIndex(domain_separator)], - [RegisterOrMemory::RegisterIndex(result)], + [message, BrilligVariable::Simple(domain_separator)], + [BrilligVariable::Simple(result)], ) = (function_arguments, function_results) { let message_vector = convert_array_or_vector(brillig_context, message, bb_func); brillig_context.black_box_op_instruction(BlackBoxOp::PedersenHash { - inputs: message_vector, + inputs: message_vector.to_heap_vector(), domain_separator: *domain_separator, output: *result, }); @@ -126,8 +126,8 @@ pub(crate) fn convert_black_box_call( } BlackBoxFunc::SchnorrVerify => { if let ( - [RegisterOrMemory::RegisterIndex(public_key_x), RegisterOrMemory::RegisterIndex(public_key_y), RegisterOrMemory::HeapArray(signature), message], - [RegisterOrMemory::RegisterIndex(result_register)], + [BrilligVariable::Simple(public_key_x), BrilligVariable::Simple(public_key_y), BrilligVariable::BrilligArray(signature), message], + [BrilligVariable::Simple(result_register)], ) = (function_arguments, function_results) { let message_hash = convert_array_or_vector(brillig_context, message, bb_func); @@ -135,8 +135,8 @@ pub(crate) fn convert_black_box_call( brillig_context.black_box_op_instruction(BlackBoxOp::SchnorrVerify { public_key_x: *public_key_x, public_key_y: *public_key_y, - message: message_hash, - signature, + message: message_hash.to_heap_vector(), + signature: signature.to_heap_vector(), result: *result_register, }); } else { @@ -145,14 +145,14 @@ pub(crate) fn convert_black_box_call( } BlackBoxFunc::FixedBaseScalarMul => { if let ( - [RegisterOrMemory::RegisterIndex(low), RegisterOrMemory::RegisterIndex(high)], - [RegisterOrMemory::HeapArray(result_array)], + [BrilligVariable::Simple(low), BrilligVariable::Simple(high)], + [BrilligVariable::BrilligArray(result_array)], ) = (function_arguments, function_results) { brillig_context.black_box_op_instruction(BlackBoxOp::FixedBaseScalarMul { low: *low, high: *high, - result: *result_array, + result: result_array.to_heap_array(), }); } else { unreachable!( @@ -166,12 +166,12 @@ pub(crate) fn convert_black_box_call( fn convert_array_or_vector( brillig_context: &mut BrilligContext, - array_or_vector: &RegisterOrMemory, + array_or_vector: &BrilligVariable, bb_func: &BlackBoxFunc, -) -> HeapVector { +) -> BrilligVector { match array_or_vector { - RegisterOrMemory::HeapArray(array) => brillig_context.array_to_vector(array), - RegisterOrMemory::HeapVector(vector) => *vector, + BrilligVariable::BrilligArray(array) => brillig_context.array_to_vector(array), + BrilligVariable::BrilligVector(vector) => *vector, _ => unreachable!( "ICE: {} expected an array or a vector, but got {:?}", bb_func.name(), diff --git a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 18fd822b07..0e06a36fd9 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -1,6 +1,6 @@ +use crate::brillig::brillig_ir::brillig_variable::{BrilligArray, BrilligVariable, BrilligVector}; use crate::brillig::brillig_ir::{ - extract_heap_array, extract_register, extract_registers, BrilligBinaryOp, BrilligContext, - BRILLIG_INTEGER_ARITHMETIC_BIT_SIZE, + BrilligBinaryOp, BrilligContext, BRILLIG_INTEGER_ARITHMETIC_BIT_SIZE, }; use crate::ssa::ir::dfg::CallStack; use crate::ssa::ir::{ @@ -13,7 +13,7 @@ use crate::ssa::ir::{ types::{NumericType, Type}, value::{Value, ValueId}, }; -use acvm::acir::brillig::{BinaryFieldOp, BinaryIntOp, HeapArray, RegisterIndex, RegisterOrMemory}; +use acvm::acir::brillig::{BinaryFieldOp, BinaryIntOp, RegisterIndex, RegisterOrMemory}; use acvm::brillig_vm::brillig::HeapVector; use acvm::FieldElement; use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; @@ -53,7 +53,7 @@ impl<'block> BrilligBlock<'block> { variables .get_available_variables(function_context) .into_iter() - .flat_map(extract_registers) + .flat_map(|variable| variable.extract_registers()) .collect(), ); let last_uses = function_context.liveness.get_last_uses(&block_id).clone(); @@ -159,7 +159,7 @@ impl<'block> BrilligBlock<'block> { .iter() .flat_map(|value_id| { let return_variable = self.convert_ssa_value(*value_id, dfg); - extract_registers(return_variable) + return_variable.extract_registers() }) .collect(); self.brillig_context.return_instruction(&return_registers); @@ -168,32 +168,44 @@ impl<'block> BrilligBlock<'block> { } /// Passes an arbitrary variable from the registers of the source to the registers of the destination - fn pass_variable(&mut self, source: RegisterOrMemory, destination: RegisterOrMemory) { + fn pass_variable(&mut self, source: BrilligVariable, destination: BrilligVariable) { match (source, destination) { ( - RegisterOrMemory::RegisterIndex(source_register), - RegisterOrMemory::RegisterIndex(destination_register), + BrilligVariable::Simple(source_register), + BrilligVariable::Simple(destination_register), ) => { self.brillig_context.mov_instruction(destination_register, source_register); } ( - RegisterOrMemory::HeapArray(HeapArray { pointer: source_pointer, .. }), - RegisterOrMemory::HeapArray(HeapArray { pointer: destination_pointer, .. }), + BrilligVariable::BrilligArray(BrilligArray { + pointer: source_pointer, + size: _, + rc: source_rc, + }), + BrilligVariable::BrilligArray(BrilligArray { + pointer: destination_pointer, + size: _, + rc: destination_rc, + }), ) => { self.brillig_context.mov_instruction(destination_pointer, source_pointer); + self.brillig_context.mov_instruction(destination_rc, source_rc); } ( - RegisterOrMemory::HeapVector(HeapVector { + BrilligVariable::BrilligVector(BrilligVector { pointer: source_pointer, size: source_size, + rc: source_rc, }), - RegisterOrMemory::HeapVector(HeapVector { + BrilligVariable::BrilligVector(BrilligVector { pointer: destination_pointer, size: destination_size, + rc: destination_rc, }), ) => { self.brillig_context.mov_instruction(destination_pointer, source_pointer); self.brillig_context.mov_instruction(destination_size, source_size); + self.brillig_context.mov_instruction(destination_rc, source_rc); } (_, _) => { unreachable!("ICE: Cannot pass value from {:?} to {:?}", source, destination); @@ -214,7 +226,7 @@ impl<'block> BrilligBlock<'block> { // In the case of arrays, the values should already be in memory and the register should // Be a valid pointer to the array. // For slices, two registers are passed, the pointer to the data and a register holding the size of the slice. - Type::Numeric(_) | Type::Array(..) | Type::Slice(..) | Type::Reference => { + Type::Numeric(_) | Type::Array(..) | Type::Slice(..) | Type::Reference(_) => { self.variables.get_block_param( self.function_context, self.block_id, @@ -264,7 +276,25 @@ impl<'block> BrilligBlock<'block> { result_value, dfg, ); - self.brillig_context.allocate_variable_instruction(address_register); + match dfg.type_of_value(result_value) { + Type::Reference(element) => match *element { + Type::Array(..) => { + self.brillig_context + .allocate_array_reference_instruction(address_register); + } + Type::Slice(..) => { + self.brillig_context + .allocate_vector_reference_instruction(address_register); + } + _ => { + self.brillig_context + .allocate_simple_reference_instruction(address_register); + } + }, + _ => { + unreachable!("ICE: Allocate on non-reference type") + } + } } Instruction::Store { address, value } => { let address_register = self.convert_ssa_register_value(*address, dfg); @@ -299,10 +329,11 @@ impl<'block> BrilligBlock<'block> { Value::ForeignFunction(func_name) => { let result_ids = dfg.instruction_results(instruction_id); - let input_registers = - vecmap(arguments, |value_id| self.convert_ssa_value(*value_id, dfg)); + let input_registers = vecmap(arguments, |value_id| { + self.convert_ssa_value(*value_id, dfg).to_register_or_memory() + }); let output_registers = vecmap(result_ids, |value_id| { - self.allocate_external_call_result(*value_id, dfg) + self.allocate_external_call_result(*value_id, dfg).to_register_or_memory() }); self.brillig_context.foreign_call_instruction( func_name.to_owned(), @@ -388,7 +419,7 @@ impl<'block> BrilligBlock<'block> { // 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 len_register_index = extract_register(len_variable); + let len_register_index = len_variable.extract_register(); self.brillig_context.mov_instruction(result_register, len_register_index); } else { self.convert_ssa_array_len(arguments[0], result_register, dfg); @@ -416,29 +447,29 @@ impl<'block> BrilligBlock<'block> { let results = dfg.instruction_results(instruction_id); - let target_len_variable = self.variables.define_variable( + let target_len = self.variables.define_register_variable( self.function_context, self.brillig_context, results[0], dfg, ); - let target_len = extract_register(target_len_variable); - let target_slice = self.variables.define_variable( - self.function_context, - self.brillig_context, - results[1], - dfg, - ); - - let heap_vec = self.brillig_context.extract_heap_vector(target_slice); + let target_vector = self + .variables + .define_variable( + self.function_context, + self.brillig_context, + results[1], + dfg, + ) + .extract_vector(); // Update the user-facing slice length self.brillig_context.mov_instruction(target_len, limb_count); self.brillig_context.radix_instruction( source, - heap_vec, + target_vector, radix, limb_count, matches!(endianness, Endian::Big), @@ -456,24 +487,29 @@ impl<'block> BrilligBlock<'block> { results[0], dfg, ); - let target_len = extract_register(target_len_variable); + let target_len = target_len_variable.extract_register(); - let target_slice = self.variables.define_variable( + let target_vector = match self.variables.define_variable( self.function_context, self.brillig_context, results[1], dfg, - ); + ) { + BrilligVariable::BrilligArray(array) => { + self.brillig_context.array_to_vector(&array) + } + BrilligVariable::BrilligVector(vector) => vector, + BrilligVariable::Simple(..) => unreachable!("ICE: ToBits on non-array"), + }; let radix = self.brillig_context.make_constant(2_usize.into()); - let heap_vec = self.brillig_context.extract_heap_vector(target_slice); // Update the user-facing slice length self.brillig_context.mov_instruction(target_len, limb_count); self.brillig_context.radix_instruction( source, - heap_vec, + target_vector, radix, limb_count, matches!(endianness, Endian::Big), @@ -523,8 +559,8 @@ impl<'block> BrilligBlock<'block> { let array_variable = self.convert_ssa_value(*array, dfg); let array_pointer = match array_variable { - RegisterOrMemory::HeapArray(HeapArray { pointer, .. }) => pointer, - RegisterOrMemory::HeapVector(HeapVector { pointer, .. }) => pointer, + BrilligVariable::BrilligArray(BrilligArray { pointer, .. }) => pointer, + BrilligVariable::BrilligVector(BrilligVector { pointer, .. }) => pointer, _ => unreachable!("ICE: array get on non-array"), }; @@ -574,6 +610,14 @@ impl<'block> BrilligBlock<'block> { self.brillig_context.deallocate_register(condition); self.brillig_context.deallocate_register(right); } + Instruction::IncrementRc { value } => { + let rc_register = match self.convert_ssa_value(*value, dfg) { + BrilligVariable::BrilligArray(BrilligArray { rc, .. }) + | BrilligVariable::BrilligVector(BrilligVector { rc, .. }) => rc, + _ => unreachable!("ICE: increment rc on non-array"), + }; + self.brillig_context.usize_op_in_place(rc_register, BinaryIntOp::Add, 1); + } _ => todo!("ICE: Instruction not supported {instruction:?}"), }; @@ -598,10 +642,7 @@ impl<'block> BrilligBlock<'block> { // Convert the arguments to registers casting those to the types of the receiving function let argument_registers: Vec = arguments .iter() - .flat_map(|argument_id| { - let variable_to_pass = self.convert_ssa_value(*argument_id, dfg); - extract_registers(variable_to_pass) - }) + .flat_map(|argument_id| self.convert_ssa_value(*argument_id, dfg).extract_registers()) .collect(); let result_ids = dfg.instruction_results(instruction_id); @@ -637,7 +678,7 @@ impl<'block> BrilligBlock<'block> { // Collect the registers that should have been returned let returned_registers: Vec = variables_assigned_to .iter() - .flat_map(|returned_variable| extract_registers(*returned_variable)) + .flat_map(|returned_variable| returned_variable.extract_registers()) .collect(); assert!( @@ -654,17 +695,13 @@ impl<'block> BrilligBlock<'block> { &mut self, array_pointer: RegisterIndex, index_register: RegisterIndex, - destination_variable: RegisterOrMemory, + destination_variable: BrilligVariable, ) { match destination_variable { - RegisterOrMemory::RegisterIndex(destination_register) => { + BrilligVariable::Simple(destination_register) => { self.brillig_context.array_get(array_pointer, index_register, destination_register); } - RegisterOrMemory::HeapArray(HeapArray { pointer, .. }) => { - self.brillig_context.array_get(array_pointer, index_register, pointer); - } - RegisterOrMemory::HeapVector(..) => { - // Vectors are stored as references inside arrays to be able to match SSA indexes + BrilligVariable::BrilligArray(..) | BrilligVariable::BrilligVector(..) => { let reference = self.brillig_context.allocate_register(); self.brillig_context.array_get(array_pointer, index_register, reference); self.brillig_context.load_variable_instruction(destination_variable, reference); @@ -677,25 +714,30 @@ impl<'block> BrilligBlock<'block> { /// With a specific value changed. fn convert_ssa_array_set( &mut self, - source_variable: RegisterOrMemory, - destination_variable: RegisterOrMemory, + source_variable: BrilligVariable, + destination_variable: BrilligVariable, index_register: RegisterIndex, - value_variable: RegisterOrMemory, + value_variable: BrilligVariable, ) { let destination_pointer = match destination_variable { - RegisterOrMemory::HeapArray(HeapArray { pointer, .. }) => pointer, - RegisterOrMemory::HeapVector(HeapVector { pointer, .. }) => pointer, + BrilligVariable::BrilligArray(BrilligArray { pointer, .. }) => pointer, + BrilligVariable::BrilligVector(BrilligVector { pointer, .. }) => pointer, _ => unreachable!("ICE: array set returns non-array"), }; - // First issue a array copy to the destination + let reference_count = match source_variable { + BrilligVariable::BrilligArray(BrilligArray { rc, .. }) + | BrilligVariable::BrilligVector(BrilligVector { rc, .. }) => rc, + _ => unreachable!("ICE: array set on non-array"), + }; + let (source_pointer, source_size_as_register) = match source_variable { - RegisterOrMemory::HeapArray(HeapArray { size, pointer }) => { + BrilligVariable::BrilligArray(BrilligArray { size, pointer, rc: _ }) => { let source_size_register = self.brillig_context.allocate_register(); self.brillig_context.const_instruction(source_size_register, size.into()); (pointer, source_size_register) } - RegisterOrMemory::HeapVector(HeapVector { size, pointer }) => { + BrilligVariable::BrilligVector(BrilligVector { size, pointer, rc: _ }) => { let source_size_register = self.brillig_context.allocate_register(); self.brillig_context.mov_instruction(source_size_register, size); (pointer, source_size_register) @@ -703,51 +745,96 @@ impl<'block> BrilligBlock<'block> { _ => unreachable!("ICE: array set on non-array"), }; - self.brillig_context - .allocate_array_instruction(destination_pointer, source_size_as_register); + let one = self.brillig_context.make_constant(1_usize.into()); + let condition = self.brillig_context.allocate_register(); - self.brillig_context.copy_array_instruction( - source_pointer, - destination_pointer, - source_size_as_register, + self.brillig_context.binary_instruction( + reference_count, + one, + condition, + BrilligBinaryOp::Field { op: BinaryFieldOp::Equals }, ); - if let RegisterOrMemory::HeapVector(HeapVector { size: target_size, .. }) = - destination_variable - { - self.brillig_context.mov_instruction(target_size, source_size_as_register); + self.brillig_context.branch_instruction(condition, |ctx, cond| { + if cond { + // Reference count is 1, we can mutate the array directly + ctx.mov_instruction(destination_pointer, source_pointer); + } else { + // First issue a array copy to the destination + ctx.allocate_array_instruction(destination_pointer, source_size_as_register); + + ctx.copy_array_instruction( + source_pointer, + destination_pointer, + source_size_as_register, + ); + } + }); + + match destination_variable { + BrilligVariable::BrilligArray(BrilligArray { rc: target_rc, .. }) => { + self.brillig_context.const_instruction(target_rc, 1_usize.into()); + } + BrilligVariable::BrilligVector(BrilligVector { + size: target_size, + rc: target_rc, + .. + }) => { + self.brillig_context.mov_instruction(target_size, source_size_as_register); + self.brillig_context.const_instruction(target_rc, 1_usize.into()); + } + _ => unreachable!("ICE: array set on non-array"), } // Then set the value in the newly created array self.store_variable_in_array(destination_pointer, index_register, value_variable); self.brillig_context.deallocate_register(source_size_as_register); + self.brillig_context.deallocate_register(one); + self.brillig_context.deallocate_register(condition); } - pub(crate) fn store_variable_in_array( - &mut self, + pub(crate) fn store_variable_in_array_with_ctx( + ctx: &mut BrilligContext, destination_pointer: RegisterIndex, index_register: RegisterIndex, - value_variable: RegisterOrMemory, + value_variable: BrilligVariable, ) { match value_variable { - RegisterOrMemory::RegisterIndex(value_register) => { - self.brillig_context.array_set(destination_pointer, index_register, value_register); + BrilligVariable::Simple(value_register) => { + ctx.array_set(destination_pointer, index_register, value_register); } - RegisterOrMemory::HeapArray(HeapArray { pointer, .. }) => { - self.brillig_context.array_set(destination_pointer, index_register, pointer); + BrilligVariable::BrilligArray(_) => { + let reference: RegisterIndex = ctx.allocate_register(); + ctx.allocate_array_reference_instruction(reference); + ctx.store_variable_instruction(reference, value_variable); + ctx.array_set(destination_pointer, index_register, reference); + ctx.deallocate_register(reference); } - RegisterOrMemory::HeapVector(_) => { - // Vectors are stored as references inside arrays to be able to match SSA indexes - let reference = self.brillig_context.allocate_register(); - self.brillig_context.allocate_variable_instruction(reference); - self.brillig_context.store_variable_instruction(reference, value_variable); - self.brillig_context.array_set(destination_pointer, index_register, reference); - self.brillig_context.deallocate_register(reference); + BrilligVariable::BrilligVector(_) => { + let reference = ctx.allocate_register(); + ctx.allocate_vector_reference_instruction(reference); + ctx.store_variable_instruction(reference, value_variable); + ctx.array_set(destination_pointer, index_register, reference); + ctx.deallocate_register(reference); } } } + pub(crate) fn store_variable_in_array( + &mut self, + destination_pointer: RegisterIndex, + index_register: RegisterIndex, + value_variable: BrilligVariable, + ) { + Self::store_variable_in_array_with_ctx( + self.brillig_context, + destination_pointer, + index_register, + value_variable, + ); + } + /// Convert the SSA slice operations to brillig slice operations fn convert_ssa_slice_intrinsic_call( &mut self, @@ -770,7 +857,7 @@ impl<'block> BrilligBlock<'block> { results[0], dfg, ) { - RegisterOrMemory::RegisterIndex(register_index) => register_index, + BrilligVariable::Simple(register_index) => register_index, _ => unreachable!("ICE: first value of a slice must be a register index"), }; @@ -781,7 +868,7 @@ impl<'block> BrilligBlock<'block> { dfg, ); - let target_vector = self.brillig_context.extract_heap_vector(target_variable); + let target_vector = target_variable.extract_vector(); let item_values = vecmap(&arguments[2..element_size + 2], |arg| { self.convert_ssa_value(*arg, dfg) }); @@ -797,7 +884,7 @@ impl<'block> BrilligBlock<'block> { results[0], dfg, ) { - RegisterOrMemory::RegisterIndex(register_index) => register_index, + BrilligVariable::Simple(register_index) => register_index, _ => unreachable!("ICE: first value of a slice must be a register index"), }; @@ -807,7 +894,7 @@ impl<'block> BrilligBlock<'block> { results[1], dfg, ); - let target_vector = self.brillig_context.extract_heap_vector(target_variable); + let target_vector = target_variable.extract_vector(); let item_values = vecmap(&arguments[2..element_size + 2], |arg| { self.convert_ssa_value(*arg, dfg) }); @@ -823,7 +910,7 @@ impl<'block> BrilligBlock<'block> { results[0], dfg, ) { - RegisterOrMemory::RegisterIndex(register_index) => register_index, + BrilligVariable::Simple(register_index) => register_index, _ => unreachable!("ICE: first value of a slice must be a register index"), }; @@ -834,7 +921,7 @@ impl<'block> BrilligBlock<'block> { dfg, ); - let target_vector = self.brillig_context.extract_heap_vector(target_variable); + let target_vector = target_variable.extract_vector(); let pop_variables = vecmap(&results[2..element_size + 2], |result| { self.variables.define_variable( @@ -856,7 +943,7 @@ impl<'block> BrilligBlock<'block> { results[element_size], dfg, ) { - RegisterOrMemory::RegisterIndex(register_index) => register_index, + BrilligVariable::Simple(register_index) => register_index, _ => unreachable!("ICE: first value of a slice must be a register index"), }; @@ -875,7 +962,7 @@ impl<'block> BrilligBlock<'block> { results[element_size + 1], dfg, ); - let target_vector = self.brillig_context.extract_heap_vector(target_variable); + let target_vector = target_variable.extract_vector(); self.update_slice_length(target_len, arguments[0], dfg, BinaryIntOp::Sub); @@ -888,7 +975,7 @@ impl<'block> BrilligBlock<'block> { results[0], dfg, ) { - RegisterOrMemory::RegisterIndex(register_index) => register_index, + BrilligVariable::Simple(register_index) => register_index, _ => unreachable!("ICE: first value of a slice must be a register index"), }; @@ -900,7 +987,7 @@ impl<'block> BrilligBlock<'block> { dfg, ); - let target_vector = self.brillig_context.extract_heap_vector(target_variable); + let target_vector = target_variable.extract_vector(); // Remove if indexing in insert is changed to flattened indexing // https://github.com/noir-lang/noir/issues/1889#issuecomment-1668048587 @@ -931,7 +1018,7 @@ impl<'block> BrilligBlock<'block> { results[0], dfg, ) { - RegisterOrMemory::RegisterIndex(register_index) => register_index, + BrilligVariable::Simple(register_index) => register_index, _ => unreachable!("ICE: first value of a slice must be a register index"), }; @@ -943,7 +1030,7 @@ impl<'block> BrilligBlock<'block> { target_id, dfg, ); - let target_vector = self.brillig_context.extract_heap_vector(target_variable); + let target_vector = target_variable.extract_vector(); // Remove if indexing in remove is changed to flattened indexing // https://github.com/noir-lang/noir/issues/1889#issuecomment-1668048587 @@ -998,7 +1085,7 @@ impl<'block> BrilligBlock<'block> { binary_op: BinaryIntOp, ) { let source_len_variable = self.convert_ssa_value(source_value, dfg); - let source_len = extract_register(source_len_variable); + let source_len = source_len_variable.extract_register(); self.brillig_context.usize_op(source_len, target_len, binary_op, 1); } @@ -1064,7 +1151,7 @@ impl<'block> BrilligBlock<'block> { } /// Converts an SSA `ValueId` into a `RegisterOrMemory`. Initializes if necessary. - fn convert_ssa_value(&mut self, value_id: ValueId, dfg: &DataFlowGraph) -> RegisterOrMemory { + fn convert_ssa_value(&mut self, value_id: ValueId, dfg: &DataFlowGraph) -> BrilligVariable { let value_id = dfg.resolve(value_id); let value = &dfg[value_id]; @@ -1082,7 +1169,7 @@ impl<'block> BrilligBlock<'block> { } else { let new_variable = self.variables.allocate_constant(self.brillig_context, value_id, dfg); - let register_index = extract_register(new_variable); + let register_index = new_variable.extract_register(); self.brillig_context.const_instruction(register_index, (*constant).into()); new_variable @@ -1097,19 +1184,21 @@ impl<'block> BrilligBlock<'block> { // Initialize the variable let pointer = match new_variable { - RegisterOrMemory::HeapArray(heap_array) => { + BrilligVariable::BrilligArray(brillig_array) => { self.brillig_context - .allocate_fixed_length_array(heap_array.pointer, array.len()); + .allocate_fixed_length_array(brillig_array.pointer, array.len()); + self.brillig_context + .const_instruction(brillig_array.rc, 1_usize.into()); - heap_array.pointer + brillig_array.pointer } - RegisterOrMemory::HeapVector(heap_vector) => { - self.brillig_context - .const_instruction(heap_vector.size, array.len().into()); + BrilligVariable::BrilligVector(vector) => { + self.brillig_context.const_instruction(vector.size, array.len().into()); self.brillig_context - .allocate_array_instruction(heap_vector.pointer, heap_vector.size); + .allocate_array_instruction(vector.pointer, vector.size); + self.brillig_context.const_instruction(vector.rc, 1_usize.into()); - heap_vector.pointer + vector.pointer } _ => unreachable!( "ICE: Cannot initialize array value created as {new_variable:?}" @@ -1138,7 +1227,7 @@ impl<'block> BrilligBlock<'block> { new_variable } } - _ => { + Value::Function(_) | Value::Intrinsic(_) | Value::ForeignFunction(_) => { todo!("ICE: Cannot convert value {value:?}") } } @@ -1151,14 +1240,14 @@ impl<'block> BrilligBlock<'block> { dfg: &DataFlowGraph, ) -> RegisterIndex { let variable = self.convert_ssa_value(value_id, dfg); - extract_register(variable) + variable.extract_register() } fn allocate_external_call_result( &mut self, result: ValueId, dfg: &DataFlowGraph, - ) -> RegisterOrMemory { + ) -> BrilligVariable { let typ = dfg[result].get_type(); match typ { Type::Numeric(_) => self.variables.define_variable( @@ -1175,8 +1264,10 @@ impl<'block> BrilligBlock<'block> { result, dfg, ); - let array = extract_heap_array(variable); + let array = variable.extract_array(); self.brillig_context.allocate_fixed_length_array(array.pointer, array.size); + self.brillig_context.const_instruction(array.rc, 1_usize.into()); + variable } Type::Slice(_) => { @@ -1186,12 +1277,14 @@ impl<'block> BrilligBlock<'block> { result, dfg, ); - let vector = self.brillig_context.extract_heap_vector(variable); + let vector = variable.extract_vector(); // Set the pointer to the current stack frame // 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.set_array_pointer(vector.pointer); + self.brillig_context.const_instruction(vector.rc, 1_usize.into()); + variable } _ => { @@ -1201,7 +1294,7 @@ impl<'block> BrilligBlock<'block> { } /// Gets the "user-facing" length of an array. - /// An array of structs with two fields would be stored as an 2 * array.len() heap array/heap vector. + /// An array of structs with two fields would be stored as an 2 * array.len() array/vector. /// So we divide the length by the number of subitems in an item to get the user-facing length. fn convert_ssa_array_len( &mut self, @@ -1213,11 +1306,11 @@ impl<'block> BrilligBlock<'block> { let element_size = dfg.type_of_value(array_id).element_size(); match array_variable { - RegisterOrMemory::HeapArray(HeapArray { size, .. }) => { + BrilligVariable::BrilligArray(BrilligArray { size, .. }) => { self.brillig_context .const_instruction(result_register, (size / element_size).into()); } - RegisterOrMemory::HeapVector(HeapVector { size, .. }) => { + BrilligVariable::BrilligVector(BrilligVector { size, .. }) => { self.brillig_context.usize_op( size, result_register, @@ -1240,7 +1333,7 @@ pub(crate) fn type_of_binary_operation(lhs_type: &Type, rhs_type: &Type) -> Type (_, Type::Function) | (Type::Function, _) => { unreachable!("Functions are invalid in binary operations") } - (_, Type::Reference) | (Type::Reference, _) => { + (_, Type::Reference(_)) | (Type::Reference(_), _) => { unreachable!("References are invalid in binary operations") } (_, Type::Array(..)) | (Type::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 eb7bab8c97..f2e698c0aa 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 @@ -1,8 +1,11 @@ -use acvm::brillig_vm::brillig::{HeapArray, HeapVector, RegisterIndex, RegisterOrMemory}; +use acvm::brillig_vm::brillig::RegisterIndex; use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use crate::{ - brillig::brillig_ir::{extract_register, BrilligContext}, + brillig::brillig_ir::{ + brillig_variable::{BrilligArray, BrilligVariable, BrilligVector}, + BrilligContext, + }, ssa::ir::{ basic_block::BasicBlockId, dfg::DataFlowGraph, @@ -16,7 +19,7 @@ use super::brillig_fn::FunctionContext; #[derive(Debug, Default)] pub(crate) struct BlockVariables { available_variables: HashSet, - available_constants: HashMap, + available_constants: HashMap, } impl BlockVariables { @@ -32,7 +35,7 @@ impl BlockVariables { pub(crate) fn get_available_variables( &self, function_context: &FunctionContext, - ) -> Vec { + ) -> Vec { self.available_variables .iter() .map(|value_id| { @@ -52,7 +55,7 @@ impl BlockVariables { brillig_context: &mut BrilligContext, value_id: ValueId, dfg: &DataFlowGraph, - ) -> RegisterOrMemory { + ) -> BrilligVariable { let value_id = dfg.resolve(value_id); let variable = allocate_value(value_id, brillig_context, dfg); @@ -74,7 +77,7 @@ impl BlockVariables { dfg: &DataFlowGraph, ) -> RegisterIndex { let variable = self.define_variable(function_context, brillig_context, value, dfg); - extract_register(variable) + variable.extract_register() } /// Removes a variable so it's not used anymore within this block. @@ -88,7 +91,7 @@ impl BlockVariables { function_context: &FunctionContext, value_id: ValueId, dfg: &DataFlowGraph, - ) -> RegisterOrMemory { + ) -> BrilligVariable { let value_id = dfg.resolve(value_id); if let Some(constant) = self.available_constants.get(&value_id) { *constant @@ -112,7 +115,7 @@ impl BlockVariables { brillig_context: &mut BrilligContext, value_id: ValueId, dfg: &DataFlowGraph, - ) -> RegisterOrMemory { + ) -> BrilligVariable { let value_id = dfg.resolve(value_id); let constant = allocate_value(value_id, brillig_context, dfg); self.available_constants.insert(value_id, constant); @@ -124,7 +127,7 @@ impl BlockVariables { &mut self, value_id: ValueId, dfg: &DataFlowGraph, - ) -> Option { + ) -> Option { let value_id = dfg.resolve(value_id); self.available_constants.get(&value_id).cloned() } @@ -141,7 +144,7 @@ impl BlockVariables { block_id: BasicBlockId, value_id: ValueId, dfg: &DataFlowGraph, - ) -> RegisterOrMemory { + ) -> BrilligVariable { let value_id = dfg.resolve(value_id); assert!( function_context @@ -166,25 +169,34 @@ pub(crate) fn allocate_value( value_id: ValueId, brillig_context: &mut BrilligContext, dfg: &DataFlowGraph, -) -> RegisterOrMemory { +) -> BrilligVariable { let typ = dfg.type_of_value(value_id); match typ { - Type::Numeric(_) | Type::Reference => { + Type::Numeric(_) | Type::Reference(_) => { let register = brillig_context.allocate_register(); - RegisterOrMemory::RegisterIndex(register) + BrilligVariable::Simple(register) } Type::Array(item_typ, elem_count) => { let pointer_register = brillig_context.allocate_register(); + let rc_register = brillig_context.allocate_register(); let size = compute_array_length(&item_typ, elem_count); - RegisterOrMemory::HeapArray(HeapArray { pointer: pointer_register, size }) + + BrilligVariable::BrilligArray(BrilligArray { + pointer: pointer_register, + size, + rc: rc_register, + }) } Type::Slice(_) => { let pointer_register = brillig_context.allocate_register(); let size_register = brillig_context.allocate_register(); - RegisterOrMemory::HeapVector(HeapVector { + let rc_register = brillig_context.allocate_register(); + + BrilligVariable::BrilligVector(BrilligVector { pointer: pointer_register, size: size_register, + rc: rc_register, }) } Type::Function => { 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 ec72ceb290..026def4ef1 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs @@ -1,9 +1,9 @@ -use acvm::brillig_vm::brillig::RegisterOrMemory; use iter_extended::vecmap; use crate::{ brillig::brillig_ir::{ artifact::{BrilligParameter, Label}, + brillig_variable::BrilligVariable, BrilligContext, }, ssa::ir::{ @@ -21,7 +21,7 @@ use super::{brillig_block_variables::allocate_value, variable_liveness::Variable pub(crate) struct FunctionContext { pub(crate) function_id: FunctionId, /// Map from SSA values its allocation. Since values can be only defined once in SSA form, we insert them here on when we allocate them at their definition. - pub(crate) ssa_value_allocations: HashMap, + pub(crate) ssa_value_allocations: HashMap, /// Block parameters are pre allocated at the function level. pub(crate) block_parameters: HashMap>, /// The block ids of the function in reverse post order. @@ -72,7 +72,7 @@ impl FunctionContext { fn ssa_type_to_parameter(typ: &Type) -> BrilligParameter { match typ { - Type::Numeric(_) | Type::Reference => BrilligParameter::Simple, + Type::Numeric(_) | Type::Reference(_) => BrilligParameter::Simple, Type::Array(item_type, size) => BrilligParameter::Array( vecmap(item_type.iter(), |item_typ| { FunctionContext::ssa_type_to_parameter(item_typ) 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 211d670e7d..6402e6f9d9 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 @@ -1,13 +1,15 @@ -use acvm::brillig_vm::brillig::{BinaryIntOp, HeapVector, RegisterIndex, RegisterOrMemory}; +use acvm::brillig_vm::brillig::{BinaryIntOp, RegisterIndex}; + +use crate::brillig::brillig_ir::brillig_variable::{BrilligVariable, BrilligVector}; use super::brillig_block::BrilligBlock; impl<'block> BrilligBlock<'block> { pub(crate) fn slice_push_back_operation( &mut self, - target_vector: HeapVector, - source_vector: HeapVector, - variables_to_insert: &[RegisterOrMemory], + target_vector: BrilligVector, + source_vector: BrilligVector, + variables_to_insert: &[BrilligVariable], ) { // First we need to allocate the target vector incrementing the size by variables_to_insert.len() self.brillig_context.usize_op( @@ -17,6 +19,8 @@ impl<'block> BrilligBlock<'block> { variables_to_insert.len(), ); self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + // We initialize the RC of the target vector to 1 + self.brillig_context.const_instruction(target_vector.rc, 1_usize.into()); // Now we copy the source vector into the target vector self.brillig_context.copy_array_instruction( @@ -40,9 +44,9 @@ impl<'block> BrilligBlock<'block> { pub(crate) fn slice_push_front_operation( &mut self, - target_vector: HeapVector, - source_vector: HeapVector, - variables_to_insert: &[RegisterOrMemory], + target_vector: BrilligVector, + source_vector: BrilligVector, + variables_to_insert: &[BrilligVariable], ) { // First we need to allocate the target vector incrementing the size by variables_to_insert.len() self.brillig_context.usize_op( @@ -52,6 +56,8 @@ impl<'block> BrilligBlock<'block> { variables_to_insert.len(), ); self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + // We initialize the RC of the target vector to 1 + self.brillig_context.const_instruction(target_vector.rc, 1_usize.into()); // Now we offset the target pointer by variables_to_insert.len() let destination_copy_pointer = self.brillig_context.allocate_register(); @@ -81,9 +87,9 @@ impl<'block> BrilligBlock<'block> { pub(crate) fn slice_pop_front_operation( &mut self, - target_vector: HeapVector, - source_vector: HeapVector, - removed_items: &[RegisterOrMemory], + target_vector: BrilligVector, + source_vector: BrilligVector, + removed_items: &[BrilligVariable], ) { // First we need to allocate the target vector decrementing the size by removed_items.len() self.brillig_context.usize_op( @@ -93,6 +99,8 @@ impl<'block> BrilligBlock<'block> { removed_items.len(), ); self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + // We initialize the RC of the target vector to 1 + self.brillig_context.const_instruction(target_vector.rc, 1_usize.into()); // Now we offset the source pointer by removed_items.len() let source_copy_pointer = self.brillig_context.allocate_register(); @@ -121,9 +129,9 @@ impl<'block> BrilligBlock<'block> { pub(crate) fn slice_pop_back_operation( &mut self, - target_vector: HeapVector, - source_vector: HeapVector, - removed_items: &[RegisterOrMemory], + target_vector: BrilligVector, + source_vector: BrilligVector, + removed_items: &[BrilligVariable], ) { // First we need to allocate the target vector decrementing the size by removed_items.len() self.brillig_context.usize_op( @@ -133,6 +141,8 @@ impl<'block> BrilligBlock<'block> { removed_items.len(), ); self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + // We initialize the RC of the target vector to 1 + self.brillig_context.const_instruction(target_vector.rc, 1_usize.into()); // Now we copy all elements except the last items into the target vector self.brillig_context.copy_array_instruction( @@ -156,10 +166,10 @@ impl<'block> BrilligBlock<'block> { pub(crate) fn slice_insert_operation( &mut self, - target_vector: HeapVector, - source_vector: HeapVector, + target_vector: BrilligVector, + source_vector: BrilligVector, index: RegisterIndex, - items: &[RegisterOrMemory], + items: &[BrilligVariable], ) { // First we need to allocate the target vector incrementing the size by items.len() self.brillig_context.usize_op( @@ -169,6 +179,8 @@ impl<'block> BrilligBlock<'block> { items.len(), ); self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + // We initialize the RC of the target vector to 1 + self.brillig_context.const_instruction(target_vector.rc, 1_usize.into()); // Copy the elements to the left of the index self.brillig_context.copy_array_instruction( @@ -226,10 +238,10 @@ impl<'block> BrilligBlock<'block> { pub(crate) fn slice_remove_operation( &mut self, - target_vector: HeapVector, - source_vector: HeapVector, + target_vector: BrilligVector, + source_vector: BrilligVector, index: RegisterIndex, - removed_items: &[RegisterOrMemory], + removed_items: &[BrilligVariable], ) { // First we need to allocate the target vector decrementing the size by removed_items.len() self.brillig_context.usize_op( @@ -239,6 +251,8 @@ impl<'block> BrilligBlock<'block> { removed_items.len(), ); self.brillig_context.allocate_array_instruction(target_vector.pointer, target_vector.size); + // We initialize the RC of the target vector to 1 + self.brillig_context.const_instruction(target_vector.rc, 1_usize.into()); // Copy the elements to the left of the index self.brillig_context.copy_array_instruction( @@ -297,11 +311,11 @@ impl<'block> BrilligBlock<'block> { pub(crate) fn convert_array_or_vector_to_vector( &mut self, - source_variable: RegisterOrMemory, - ) -> HeapVector { + source_variable: BrilligVariable, + ) -> BrilligVector { match source_variable { - RegisterOrMemory::HeapVector(source_vector) => source_vector, - RegisterOrMemory::HeapArray(source_array) => { + BrilligVariable::BrilligVector(source_vector) => source_vector, + BrilligVariable::BrilligArray(source_array) => { self.brillig_context.array_to_vector(&source_array) } _ => unreachable!("ICE: unsupported slice push back source {:?}", source_variable), @@ -313,13 +327,16 @@ impl<'block> BrilligBlock<'block> { mod tests { use std::vec; - use acvm::acir::brillig::{HeapVector, Value}; - use acvm::brillig_vm::brillig::{RegisterIndex, RegisterOrMemory}; + use acvm::acir::brillig::Value; + use acvm::brillig_vm::brillig::RegisterIndex; use crate::brillig::brillig_gen::brillig_block::BrilligBlock; use crate::brillig::brillig_gen::brillig_block_variables::BlockVariables; use crate::brillig::brillig_gen::brillig_fn::FunctionContext; use crate::brillig::brillig_ir::artifact::BrilligParameter; + use crate::brillig::brillig_ir::brillig_variable::{ + BrilligArray, BrilligVariable, BrilligVector, + }; use crate::brillig::brillig_ir::tests::{ create_and_run_vm, create_context, create_entry_point_bytecode, }; @@ -373,33 +390,44 @@ mod tests { let (_, mut function_context, mut context) = create_test_environment(); // Allocate the parameters - let array_pointer = context.allocate_register(); + let array_variable = BrilligArray { + pointer: context.allocate_register(), + size: array.len(), + rc: context.allocate_register(), + }; let item_to_insert = context.allocate_register(); // Cast the source array to a vector - let array_size = context.make_constant(array.len().into()); + let source_vector = context.array_to_vector(&array_variable); // Allocate the results - let copied_array_pointer = context.allocate_register(); - let copied_array_size = context.allocate_register(); + let target_vector = BrilligVector { + pointer: context.allocate_register(), + size: context.allocate_register(), + rc: context.allocate_register(), + }; let mut block = create_brillig_block(&mut function_context, &mut context); if push_back { block.slice_push_back_operation( - HeapVector { pointer: copied_array_pointer, size: copied_array_size }, - HeapVector { pointer: array_pointer, size: array_size }, - &[RegisterOrMemory::RegisterIndex(item_to_insert)], + target_vector, + source_vector, + &[BrilligVariable::Simple(item_to_insert)], ); } else { block.slice_push_front_operation( - HeapVector { pointer: copied_array_pointer, size: copied_array_size }, - HeapVector { pointer: array_pointer, size: array_size }, - &[RegisterOrMemory::RegisterIndex(item_to_insert)], + target_vector, + source_vector, + &[BrilligVariable::Simple(item_to_insert)], ); } - context.return_instruction(&[copied_array_pointer, copied_array_size]); + context.return_instruction(&[ + target_vector.pointer, + target_vector.rc, + target_vector.size, + ]); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let vm = create_and_run_vm( @@ -465,34 +493,45 @@ mod tests { let (_, mut function_context, mut context) = create_test_environment(); // Allocate the parameters - let array_pointer = context.allocate_register(); + let array_variable = BrilligArray { + pointer: context.allocate_register(), + size: array.len(), + rc: context.allocate_register(), + }; // Cast the source array to a vector - let array_size = context.make_constant(array.len().into()); + let source_vector = context.array_to_vector(&array_variable); // Allocate the results - let copied_array_pointer = context.allocate_register(); + let target_vector = BrilligVector { + pointer: context.allocate_register(), + size: context.allocate_register(), + rc: context.allocate_register(), + }; let removed_item = context.allocate_register(); - let copied_array_size = context.allocate_register(); - let mut block = create_brillig_block(&mut function_context, &mut context); if pop_back { block.slice_pop_back_operation( - HeapVector { pointer: copied_array_pointer, size: copied_array_size }, - HeapVector { pointer: array_pointer, size: array_size }, - &[RegisterOrMemory::RegisterIndex(removed_item)], + target_vector, + source_vector, + &[BrilligVariable::Simple(removed_item)], ); } else { block.slice_pop_front_operation( - HeapVector { pointer: copied_array_pointer, size: copied_array_size }, - HeapVector { pointer: array_pointer, size: array_size }, - &[RegisterOrMemory::RegisterIndex(removed_item)], + target_vector, + source_vector, + &[BrilligVariable::Simple(removed_item)], ); } - context.return_instruction(&[copied_array_pointer, copied_array_size, removed_item]); + context.return_instruction(&[ + target_vector.pointer, + target_vector.rc, + target_vector.size, + removed_item, + ]); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let vm = create_and_run_vm(array.clone(), vec![Value::from(0_usize)], &bytecode); @@ -557,28 +596,38 @@ mod tests { let (_, mut function_context, mut context) = create_test_environment(); // Allocate the parameters - let array_pointer = context.allocate_register(); + let array_variable = BrilligArray { + pointer: context.allocate_register(), + size: array.len(), + rc: context.allocate_register(), + }; let item_to_insert = context.allocate_register(); let index_to_insert = context.allocate_register(); // Cast the source array to a vector - let array_size = context.make_constant(array.len().into()); + let source_vector = context.array_to_vector(&array_variable); // Allocate the results - let copied_array_pointer = context.allocate_register(); - - let copied_array_size = context.allocate_register(); + let target_vector = BrilligVector { + pointer: context.allocate_register(), + size: context.allocate_register(), + rc: context.allocate_register(), + }; let mut block = create_brillig_block(&mut function_context, &mut context); block.slice_insert_operation( - HeapVector { pointer: copied_array_pointer, size: copied_array_size }, - HeapVector { pointer: array_pointer, size: array_size }, + target_vector, + source_vector, index_to_insert, - &[RegisterOrMemory::RegisterIndex(item_to_insert)], + &[BrilligVariable::Simple(item_to_insert)], ); - context.return_instruction(&[copied_array_pointer, copied_array_size]); + context.return_instruction(&[ + target_vector.pointer, + target_vector.rc, + target_vector.size, + ]); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let vm = create_and_run_vm( @@ -679,28 +728,39 @@ mod tests { let (_, mut function_context, mut context) = create_test_environment(); // Allocate the parameters - let array_pointer = context.allocate_register(); + let array_variable = BrilligArray { + pointer: context.allocate_register(), + size: array.len(), + rc: context.allocate_register(), + }; let index_to_insert = context.allocate_register(); // Cast the source array to a vector - let array_size = context.make_constant(array.len().into()); + let source_vector = context.array_to_vector(&array_variable); // Allocate the results - let copied_array_pointer = context.allocate_register(); + let target_vector = BrilligVector { + pointer: context.allocate_register(), + size: context.allocate_register(), + rc: context.allocate_register(), + }; let removed_item = context.allocate_register(); - let copied_array_size = context.allocate_register(); - let mut block = create_brillig_block(&mut function_context, &mut context); block.slice_remove_operation( - HeapVector { pointer: copied_array_pointer, size: copied_array_size }, - HeapVector { pointer: array_pointer, size: array_size }, + target_vector, + source_vector, index_to_insert, - &[RegisterOrMemory::RegisterIndex(removed_item)], + &[BrilligVariable::Simple(removed_item)], ); - context.return_instruction(&[copied_array_pointer, copied_array_size, removed_item]); + context.return_instruction(&[ + target_vector.pointer, + target_vector.rc, + target_vector.size, + removed_item, + ]); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let vm = create_and_run_vm(array.clone(), vec![Value::from(0_usize), index], &bytecode); 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 d57196288b..05978c2c6a 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/variable_liveness.rs @@ -332,7 +332,7 @@ mod test { let v0 = builder.add_parameter(Type::field()); let v1 = builder.add_parameter(Type::field()); - let v3 = builder.insert_allocate(); + let v3 = builder.insert_allocate(Type::field()); let zero = builder.numeric_constant(0u128, Type::field()); builder.insert_store(v3, zero); @@ -439,7 +439,7 @@ mod test { let v0 = builder.add_parameter(Type::field()); let v1 = builder.add_parameter(Type::field()); - let v3 = builder.insert_allocate(); + let v3 = builder.insert_allocate(Type::field()); let zero = builder.numeric_constant(0u128, Type::field()); builder.insert_store(v3, zero); diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index 880ae95dcd..ff182aaa7d 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -5,6 +5,7 @@ //! ssa types and types in this module. //! A similar paradigm can be seen with the `acir_ir` module. pub(crate) mod artifact; +pub(crate) mod brillig_variable; pub(crate) mod debug_show; pub(crate) mod registers; @@ -14,12 +15,13 @@ use crate::ssa::ir::dfg::CallStack; use self::{ artifact::{BrilligArtifact, UnresolvedJumpLocation}, + brillig_variable::{BrilligArray, BrilligVariable, BrilligVector}, registers::BrilligRegistersContext, }; use acvm::{ acir::brillig::{ - BinaryFieldOp, BinaryIntOp, BlackBoxOp, HeapArray, HeapVector, Opcode as BrilligOpcode, - RegisterIndex, RegisterOrMemory, Value, + BinaryFieldOp, BinaryIntOp, BlackBoxOp, Opcode as BrilligOpcode, RegisterIndex, + RegisterOrMemory, Value, }, FieldElement, }; @@ -88,6 +90,8 @@ pub(crate) struct BrilligContext { context_label: String, /// Section label, used to separate sections of code section_label: usize, + /// Stores the next available section + next_section: usize, /// IR printer debug_show: DebugShow, } @@ -100,6 +104,7 @@ impl BrilligContext { registers: BrilligRegistersContext::new(), context_label: String::default(), section_label: 0, + next_section: 1, debug_show: DebugShow::new(enable_debug_trace), } } @@ -161,10 +166,14 @@ impl BrilligContext { /// Allocates a variable in memory and stores the /// pointer to the array in `pointer_register` - pub(crate) fn allocate_variable_instruction(&mut self, pointer_register: RegisterIndex) { + fn allocate_variable_reference_instruction( + &mut self, + pointer_register: RegisterIndex, + size: usize, + ) { self.debug_show.allocate_instruction(pointer_register); - // A variable can be stored in up to two values, so we reserve two values for that. - let size_register = self.make_constant(2_u128.into()); + // A variable can be stored in up to three values, so we reserve three values for that. + let size_register = self.make_constant(size.into()); self.push_opcode(BrilligOpcode::Mov { destination: pointer_register, source: ReservedRegisters::stack_pointer(), @@ -177,6 +186,30 @@ impl BrilligContext { ); } + pub(crate) fn allocate_simple_reference_instruction( + &mut self, + pointer_register: RegisterIndex, + ) { + self.allocate_variable_reference_instruction(pointer_register, 1); + } + + pub(crate) fn allocate_array_reference_instruction(&mut self, pointer_register: RegisterIndex) { + self.allocate_variable_reference_instruction( + pointer_register, + BrilligArray::registers_count(), + ); + } + + pub(crate) fn allocate_vector_reference_instruction( + &mut self, + pointer_register: RegisterIndex, + ) { + self.allocate_variable_reference_instruction( + pointer_register, + BrilligVector::registers_count(), + ); + } + /// Gets the value in the array at index `index` and stores it in `result` pub(crate) fn array_get( &mut self, @@ -253,8 +286,8 @@ impl BrilligContext { { let iterator_register = self.make_constant(0_u128.into()); - let loop_label = self.next_section_label(); - self.enter_next_section(); + let (loop_section, loop_label) = self.reserve_next_section_label(); + self.enter_section(loop_section); // Loop body @@ -267,7 +300,7 @@ impl BrilligContext { BinaryIntOp::LessThan, ); - let exit_loop_label = self.next_section_label(); + let (exit_loop_section, exit_loop_label) = self.reserve_next_section_label(); self.not_instruction(iterator_less_than_iterations, 1, iterator_less_than_iterations); self.jump_if_instruction(iterator_less_than_iterations, exit_loop_label); @@ -281,12 +314,41 @@ impl BrilligContext { self.jump_instruction(loop_label); // Exit the loop - self.enter_next_section(); + self.enter_section(exit_loop_section); + // Deallocate our temporary registers self.deallocate_register(iterator_less_than_iterations); self.deallocate_register(iterator_register); } + /// This instruction will issue an if-then branch that will check if the condition is true + /// and if so, perform the instructions given in `f(self, true)` and otherwise perform the + /// instructions given in `f(self, false)`. A boolean is passed instead of two separate + /// functions to allow the given function to mutably alias its environment. + pub(crate) fn branch_instruction( + &mut self, + condition: RegisterIndex, + mut f: impl FnMut(&mut BrilligContext, bool), + ) { + // Reserve 3 sections + let (then_section, then_label) = self.reserve_next_section_label(); + let (otherwise_section, otherwise_label) = self.reserve_next_section_label(); + let (end_section, end_label) = self.reserve_next_section_label(); + + self.jump_if_instruction(condition, then_label.clone()); + self.jump_instruction(otherwise_label.clone()); + + self.enter_section(then_section); + f(self, true); + self.jump_instruction(end_label.clone()); + + self.enter_section(otherwise_section); + f(self, false); + self.jump_instruction(end_label.clone()); + + self.enter_section(end_section); + } + /// Adds a label to the next opcode pub(crate) fn enter_context(&mut self, label: T) { self.debug_show.enter_context(label.to_string()); @@ -299,23 +361,25 @@ impl BrilligContext { .add_label_at_position(self.current_section_label(), self.obj.index_of_next_opcode()); } - /// Increments the section label and adds a section label to the next opcode - fn enter_next_section(&mut self) { - self.section_label += 1; + /// Enter the given section + fn enter_section(&mut self, section: usize) { + self.section_label = section; self.obj .add_label_at_position(self.current_section_label(), self.obj.index_of_next_opcode()); } + /// Create, reserve, and return a new section label. + fn reserve_next_section_label(&mut self) -> (usize, String) { + let section = self.next_section; + self.next_section += 1; + (section, self.compute_section_label(section)) + } + /// Internal function used to compute the section labels fn compute_section_label(&self, section: usize) -> String { format!("{}-{}", self.context_label, section) } - /// Returns the next section label - fn next_section_label(&self) -> String { - self.compute_section_label(self.section_label + 1) - } - /// Returns the current section label fn current_section_label(&self) -> String { self.compute_section_label(self.section_label) @@ -371,15 +435,13 @@ impl BrilligContext { assert_message: Option, ) { self.debug_show.constrain_instruction(condition); - self.add_unresolved_jump( - BrilligOpcode::JumpIf { condition, location: 0 }, - self.next_section_label(), - ); + let (next_section, next_label) = self.reserve_next_section_label(); + self.add_unresolved_jump(BrilligOpcode::JumpIf { condition, location: 0 }, next_label); self.push_opcode(BrilligOpcode::Trap); if let Some(assert_message) = assert_message { self.obj.add_assert_message_to_last_opcode(assert_message); } - self.enter_next_section(); + self.enter_section(next_section); } /// Processes a return instruction. @@ -528,17 +590,24 @@ impl BrilligContext { /// Loads a variable stored previously pub(crate) fn load_variable_instruction( &mut self, - destination: RegisterOrMemory, + destination: BrilligVariable, variable_pointer: RegisterIndex, ) { match destination { - RegisterOrMemory::RegisterIndex(register_index) => { + BrilligVariable::Simple(register_index) => { self.load_instruction(register_index, variable_pointer); } - RegisterOrMemory::HeapArray(HeapArray { pointer, .. }) => { + BrilligVariable::BrilligArray(BrilligArray { pointer, size: _, rc }) => { self.load_instruction(pointer, variable_pointer); + + let rc_pointer = self.allocate_register(); + self.mov_instruction(rc_pointer, variable_pointer); + self.usize_op_in_place(rc_pointer, BinaryIntOp::Add, 1_usize); + + self.load_instruction(rc, rc_pointer); + self.deallocate_register(rc_pointer); } - RegisterOrMemory::HeapVector(HeapVector { pointer, size }) => { + BrilligVariable::BrilligVector(BrilligVector { pointer, size, rc }) => { self.load_instruction(pointer, variable_pointer); let size_pointer = self.allocate_register(); @@ -547,6 +616,13 @@ impl BrilligContext { self.load_instruction(size, size_pointer); self.deallocate_register(size_pointer); + + let rc_pointer = self.allocate_register(); + self.mov_instruction(rc_pointer, variable_pointer); + self.usize_op_in_place(rc_pointer, BinaryIntOp::Add, 2_usize); + + self.load_instruction(rc, rc_pointer); + self.deallocate_register(rc_pointer); } } } @@ -565,32 +641,38 @@ impl BrilligContext { pub(crate) fn store_variable_instruction( &mut self, variable_pointer: RegisterIndex, - source: RegisterOrMemory, + source: BrilligVariable, ) { - let size_pointer = self.allocate_register(); - self.mov_instruction(size_pointer, variable_pointer); - self.usize_op_in_place(size_pointer, BinaryIntOp::Add, 1_usize); - match source { - RegisterOrMemory::RegisterIndex(register_index) => { + BrilligVariable::Simple(register_index) => { self.store_instruction(variable_pointer, register_index); - let size_constant = self.make_constant(Value::from(1_usize)); - self.store_instruction(size_pointer, size_constant); - self.deallocate_register(size_constant); } - RegisterOrMemory::HeapArray(HeapArray { pointer, size }) => { + BrilligVariable::BrilligArray(BrilligArray { pointer, size: _, rc }) => { self.store_instruction(variable_pointer, pointer); - let size_constant = self.make_constant(Value::from(size)); - self.store_instruction(size_pointer, size_constant); - self.deallocate_register(size_constant); + + let rc_pointer: RegisterIndex = self.allocate_register(); + self.mov_instruction(rc_pointer, variable_pointer); + self.usize_op_in_place(rc_pointer, BinaryIntOp::Add, 1_usize); + self.store_instruction(rc_pointer, rc); + self.deallocate_register(rc_pointer); } - RegisterOrMemory::HeapVector(HeapVector { pointer, size }) => { + BrilligVariable::BrilligVector(BrilligVector { pointer, size, rc }) => { self.store_instruction(variable_pointer, pointer); + + let size_pointer = self.allocate_register(); + self.mov_instruction(size_pointer, variable_pointer); + self.usize_op_in_place(size_pointer, BinaryIntOp::Add, 1_usize); self.store_instruction(size_pointer, size); + + let rc_pointer: RegisterIndex = self.allocate_register(); + self.mov_instruction(rc_pointer, variable_pointer); + self.usize_op_in_place(rc_pointer, BinaryIntOp::Add, 2_usize); + self.store_instruction(rc_pointer, rc); + + self.deallocate_register(size_pointer); + self.deallocate_register(rc_pointer); } } - - self.deallocate_register(size_pointer); } /// Emits a truncate instruction. @@ -725,14 +807,14 @@ impl BrilligContext { } /// Saves all of the registers that have been used up until this point. - fn save_registers_of_vars(&mut self, vars: &[RegisterOrMemory]) -> Vec { + fn save_registers_of_vars(&mut self, vars: &[BrilligVariable]) -> Vec { // Save all of the used registers at this point in memory // because the function call will/may overwrite them. // // Note that here it is important that the stack pointer register is at register 0, // as after the first register save we add to the pointer. let mut used_registers: Vec<_> = - vars.iter().flat_map(|var| extract_registers(*var)).collect(); + vars.iter().flat_map(|var| var.extract_registers()).collect(); // Also dump the previous stack pointer used_registers.push(ReservedRegisters::previous_stack_pointer()); @@ -811,7 +893,7 @@ impl BrilligContext { pub(crate) fn pre_call_save_registers_prep_args( &mut self, arguments: &[RegisterIndex], - variables_to_save: &[RegisterOrMemory], + variables_to_save: &[BrilligVariable], ) -> Vec { // Save all the registers we have used to the stack. let saved_registers = self.save_registers_of_vars(variables_to_save); @@ -852,9 +934,9 @@ impl BrilligContext { } /// Utility method to transform a HeapArray to a HeapVector by making a runtime constant with the size. - pub(crate) fn array_to_vector(&mut self, array: &HeapArray) -> HeapVector { + pub(crate) fn array_to_vector(&mut self, array: &BrilligArray) -> BrilligVector { let size_register = self.make_constant(array.size.into()); - HeapVector { size: size_register, pointer: array.pointer } + BrilligVector { size: size_register, pointer: array.pointer, rc: array.rc } } /// Issues a blackbox operation. @@ -868,12 +950,13 @@ impl BrilligContext { pub(crate) fn radix_instruction( &mut self, source: RegisterIndex, - target_vector: HeapVector, + target_vector: BrilligVector, radix: RegisterIndex, limb_count: RegisterIndex, big_endian: bool, ) { self.mov_instruction(target_vector.size, limb_count); + self.const_instruction(target_vector.rc, 1_usize.into()); self.allocate_array_instruction(target_vector.pointer, target_vector.size); let shifted_register = self.allocate_register(); @@ -914,7 +997,7 @@ impl BrilligContext { } /// This instruction will reverse the order of the elements in a vector. - pub(crate) fn reverse_vector_in_place_instruction(&mut self, vector: HeapVector) { + pub(crate) fn reverse_vector_in_place_instruction(&mut self, vector: BrilligVector) { let iteration_count = self.allocate_register(); self.usize_op(vector.size, iteration_count, BinaryIntOp::UnsignedDiv, 2); @@ -949,51 +1032,12 @@ impl BrilligContext { self.deallocate_register(index_at_end_of_array); } - pub(crate) fn extract_heap_vector(&mut self, variable: RegisterOrMemory) -> HeapVector { - match variable { - RegisterOrMemory::HeapVector(vector) => vector, - RegisterOrMemory::HeapArray(array) => { - let size = self.allocate_register(); - self.const_instruction(size, array.size.into()); - HeapVector { pointer: array.pointer, size } - } - _ => unreachable!("ICE: Expected vector, got {variable:?}"), - } - } - /// Sets a current call stack that the next pushed opcodes will be associated with. pub(crate) fn set_call_stack(&mut self, call_stack: CallStack) { self.obj.set_call_stack(call_stack); } } -pub(crate) fn extract_register(variable: RegisterOrMemory) -> RegisterIndex { - match variable { - RegisterOrMemory::RegisterIndex(register_index) => register_index, - _ => unreachable!("ICE: Expected register, got {variable:?}"), - } -} - -pub(crate) fn extract_heap_array(variable: RegisterOrMemory) -> HeapArray { - match variable { - RegisterOrMemory::HeapArray(array) => array, - _ => unreachable!("ICE: Expected array, got {variable:?}"), - } -} - -/// Collects the registers that a given variable is stored in. -pub(crate) fn extract_registers(variable: RegisterOrMemory) -> Vec { - match variable { - RegisterOrMemory::RegisterIndex(register_index) => vec![register_index], - RegisterOrMemory::HeapArray(array) => { - vec![array.pointer] - } - RegisterOrMemory::HeapVector(vector) => { - vec![vector.pointer, vector.size] - } - } -} - /// Type to encapsulate the binary operation types in Brillig #[derive(Clone)] pub(crate) enum BrilligBinaryOp { diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/brillig_variable.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/brillig_variable.rs new file mode 100644 index 0000000000..46c54d55ec --- /dev/null +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/brillig_variable.rs @@ -0,0 +1,99 @@ +use acvm::brillig_vm::brillig::{HeapArray, HeapVector, RegisterIndex, RegisterOrMemory}; +use serde::{Deserialize, Serialize}; + +/// The representation of a noir array in the Brillig IR +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)] +pub(crate) struct BrilligArray { + pub(crate) pointer: RegisterIndex, + pub(crate) size: usize, + pub(crate) rc: RegisterIndex, +} + +impl BrilligArray { + pub(crate) fn to_heap_array(self) -> HeapArray { + HeapArray { pointer: self.pointer, size: self.size } + } + + pub(crate) fn registers_count() -> usize { + 2 + } + + pub(crate) fn extract_registers(self) -> Vec { + vec![self.pointer, self.rc] + } +} + +/// The representation of a noir slice in the Brillig IR +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)] +pub(crate) struct BrilligVector { + pub(crate) pointer: RegisterIndex, + pub(crate) size: RegisterIndex, + pub(crate) rc: RegisterIndex, +} + +impl BrilligVector { + pub(crate) fn to_heap_vector(self) -> HeapVector { + HeapVector { pointer: self.pointer, size: self.size } + } + + pub(crate) fn registers_count() -> usize { + 3 + } + + pub(crate) fn extract_registers(self) -> Vec { + vec![self.pointer, self.size, self.rc] + } +} + +/// The representation of a noir value in the Brillig IR +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)] +pub(crate) enum BrilligVariable { + Simple(RegisterIndex), + BrilligArray(BrilligArray), + BrilligVector(BrilligVector), +} + +impl BrilligVariable { + pub(crate) fn extract_register(self) -> RegisterIndex { + match self { + BrilligVariable::Simple(register_index) => register_index, + _ => unreachable!("ICE: Expected register, got {self:?}"), + } + } + + pub(crate) fn extract_array(self) -> BrilligArray { + match self { + BrilligVariable::BrilligArray(array) => array, + _ => unreachable!("ICE: Expected array, got {self:?}"), + } + } + + pub(crate) fn extract_vector(self) -> BrilligVector { + match self { + BrilligVariable::BrilligVector(vector) => vector, + _ => unreachable!("ICE: Expected vector, got {self:?}"), + } + } + + pub(crate) fn extract_registers(self) -> Vec { + match self { + BrilligVariable::Simple(register_index) => vec![register_index], + BrilligVariable::BrilligArray(array) => array.extract_registers(), + BrilligVariable::BrilligVector(vector) => vector.extract_registers(), + } + } + + pub(crate) fn to_register_or_memory(self) -> RegisterOrMemory { + match self { + BrilligVariable::Simple(register_index) => { + RegisterOrMemory::RegisterIndex(register_index) + } + BrilligVariable::BrilligArray(array) => { + RegisterOrMemory::HeapArray(array.to_heap_array()) + } + BrilligVariable::BrilligVector(vector) => { + RegisterOrMemory::HeapVector(vector.to_heap_vector()) + } + } + } +} diff --git a/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs b/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs index fb426ad687..4861598823 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs @@ -2,6 +2,7 @@ use crate::brillig::brillig_ir::ReservedRegisters; use super::{ artifact::{BrilligArtifact, BrilligParameter}, + brillig_variable::{BrilligArray, BrilligVariable}, debug_show::DebugShow, registers::BrilligRegistersContext, BrilligContext, @@ -20,6 +21,7 @@ impl BrilligContext { registers: BrilligRegistersContext::new(), context_label: String::default(), section_label: 0, + next_section: 1, debug_show: DebugShow::new(false), }; @@ -32,18 +34,39 @@ impl BrilligContext { } /// Adds the instructions needed to handle entry point parameters - /// - /// And sets the starting value of the reserved registers + /// The runtime will leave the parameters in the first `n` registers. + /// Arrays will be passed as pointers to the first element, with all the nested arrays flattened. + /// First, reserve the registers that contain the parameters. + /// This function also sets the starting value of the reserved registers fn entry_point_instruction(&mut self, arguments: Vec) { - // Translate the inputs by the reserved registers offset - for i in (0..arguments.len()).rev() { - self.push_opcode(BrilligOpcode::Mov { - destination: ReservedRegisters::user_register_index(i), - source: RegisterIndex::from(i), - }); - // Make sure we don't overwrite the arguments - self.allocate_register(); - } + let preallocated_registers: Vec<_> = + arguments.iter().enumerate().map(|(i, _)| RegisterIndex::from(i)).collect(); + self.set_allocated_registers(preallocated_registers.clone()); + + // Then allocate and initialize the variables that will hold the parameters + let argument_variables: Vec<_> = arguments + .iter() + .zip(preallocated_registers) + .map(|(argument, param_register)| match argument { + BrilligParameter::Simple => { + let variable_register = self.allocate_register(); + self.mov_instruction(variable_register, param_register); + BrilligVariable::Simple(variable_register) + } + BrilligParameter::Array(item_types, item_count) => { + let pointer_register = self.allocate_register(); + let rc_register = self.allocate_register(); + self.mov_instruction(pointer_register, param_register); + self.const_instruction(rc_register, 1_usize.into()); + BrilligVariable::BrilligArray(BrilligArray { + pointer: pointer_register, + size: item_types.len() * item_count, + rc: rc_register, + }) + } + BrilligParameter::Slice(_) => unimplemented!("Unsupported slices as parameter"), + }) + .collect(); // Calculate the initial value for the stack pointer register let size_arguments_memory: usize = arguments @@ -65,16 +88,24 @@ impl BrilligContext { value: 0_usize.into(), }); - for (index, parameter) in arguments.iter().enumerate() { + // Deflatten the arrays + for (parameter, assigned_variable) in arguments.iter().zip(&argument_variables) { if let BrilligParameter::Array(item_type, item_count) = parameter { if item_type.iter().any(|param| !matches!(param, BrilligParameter::Simple)) { - let pointer_register = ReservedRegisters::user_register_index(index); + let pointer_register = assigned_variable.extract_array().pointer; let deflattened_register = self.deflatten_array(item_type, *item_count, pointer_register); self.mov_instruction(pointer_register, deflattened_register); } } } + + // Move the parameters to the first user defined registers, to follow function call convention. + for (i, register) in + argument_variables.into_iter().flat_map(|arg| arg.extract_registers()).enumerate() + { + self.mov_instruction(ReservedRegisters::user_register_index(i), register); + } } /// Computes the size of a parameter if it was flattened @@ -92,6 +123,7 @@ impl BrilligContext { } /// Deflatten an array by recursively allocating nested arrays and copying the plain values. + /// Returns the pointer to the deflattened items. fn deflatten_array( &mut self, item_type: &[BrilligParameter], @@ -139,13 +171,25 @@ impl BrilligContext { *nested_array_item_count, nested_array_pointer, ); - self.array_set( - deflattened_array_pointer, - target_index, - deflattened_nested_array_pointer, + let reference = self.allocate_register(); + let rc = self.allocate_register(); + self.const_instruction(rc, 1_usize.into()); + + self.allocate_array_reference_instruction(reference); + self.store_variable_instruction( + reference, + BrilligVariable::BrilligArray(BrilligArray { + pointer: deflattened_nested_array_pointer, + size: nested_array_item_type.len() * nested_array_item_count, + rc, + }), ); + self.array_set(deflattened_array_pointer, target_index, reference); + self.deallocate_register(nested_array_pointer); + self.deallocate_register(reference); + self.deallocate_register(rc); source_offset += BrilligContext::flattened_size(subitem); } @@ -163,21 +207,36 @@ impl BrilligContext { } /// Adds the instructions needed to handle return parameters + /// The runtime expects the results in the first `n` registers. + /// Arrays are expected to be returned as pointers to the first element with all the nested arrays flattened. + /// However, the function called returns variables (that have extra data) and the returned arrays are unflattened. fn exit_point_instruction(&mut self, return_parameters: Vec) { - // Make sure we don't overwrite the return parameters - return_parameters.iter().for_each(|_| { - self.allocate_register(); - }); - - for (index, ret) in return_parameters.iter().enumerate() { - if let BrilligParameter::Array(item_type, item_count) = ret { + // First, we allocate the registers that hold the returned variables from the function call. + self.set_allocated_registers(vec![]); + let returned_variables: Vec<_> = return_parameters + .iter() + .map(|return_parameter| match return_parameter { + BrilligParameter::Simple => BrilligVariable::Simple(self.allocate_register()), + BrilligParameter::Array(item_types, item_count) => { + BrilligVariable::BrilligArray(BrilligArray { + pointer: self.allocate_register(), + size: item_types.len() * item_count, + rc: self.allocate_register(), + }) + } + BrilligParameter::Slice(..) => unreachable!("ICE: Cannot return slices"), + }) + .collect(); + // Now, we unflatten the returned arrays + for (return_param, returned_variable) in return_parameters.iter().zip(&returned_variables) { + if let BrilligParameter::Array(item_type, item_count) = return_param { if item_type.iter().any(|item| !matches!(item, BrilligParameter::Simple)) { - let returned_pointer = ReservedRegisters::user_register_index(index); + let returned_pointer = returned_variable.extract_array().pointer; let flattened_array_pointer = self.allocate_register(); self.allocate_fixed_length_array( flattened_array_pointer, - BrilligContext::flattened_size(ret), + BrilligContext::flattened_size(return_param), ); self.flatten_array( @@ -191,16 +250,18 @@ impl BrilligContext { } } } - // We want all functions to follow the calling convention of returning + // The VM expects us to follow the calling convention of returning // their results in the first `n` registers. So we to move the return values // to the first `n` registers once completed. // Move the results to registers 0..n - for i in 0..return_parameters.len() { - self.push_opcode(BrilligOpcode::Mov { - destination: i.into(), - source: ReservedRegisters::user_register_index(i), - }); + for (i, returned_variable) in returned_variables.into_iter().enumerate() { + let register = match returned_variable { + BrilligVariable::Simple(register) => register, + BrilligVariable::BrilligArray(array) => array.pointer, + BrilligVariable::BrilligVector(vector) => vector.pointer, + }; + self.push_opcode(BrilligOpcode::Mov { destination: i.into(), source: register }); } self.push_opcode(BrilligOpcode::Stop); } @@ -237,11 +298,22 @@ impl BrilligContext { target_offset += 1; } BrilligParameter::Array(nested_array_item_type, nested_array_item_count) => { - let nested_array_pointer = self.allocate_register(); + let nested_array_reference = self.allocate_register(); self.array_get( deflattened_array_pointer, source_index, - nested_array_pointer, + nested_array_reference, + ); + + let nested_array_variable = BrilligVariable::BrilligArray(BrilligArray { + pointer: self.allocate_register(), + size: nested_array_item_type.len() * nested_array_item_count, + rc: self.allocate_register(), + }); + + self.load_variable_instruction( + nested_array_variable, + nested_array_reference, ); let flattened_nested_array_pointer = self.allocate_register(); @@ -262,11 +334,15 @@ impl BrilligContext { nested_array_item_type, *nested_array_item_count, flattened_nested_array_pointer, - nested_array_pointer, + nested_array_variable.extract_array().pointer, ); - self.deallocate_register(nested_array_pointer); + self.deallocate_register(nested_array_reference); self.deallocate_register(flattened_nested_array_pointer); + nested_array_variable + .extract_registers() + .into_iter() + .for_each(|register| self.deallocate_register(register)); target_offset += BrilligContext::flattened_size(subitem); } @@ -288,6 +364,7 @@ mod tests { use crate::brillig::brillig_ir::{ artifact::BrilligParameter, + brillig_variable::BrilligArray, tests::{create_and_run_vm, create_context, create_entry_point_bytecode}, }; @@ -332,18 +409,24 @@ mod tests { Value::from(4_usize), Value::from(5_usize), Value::from(6_usize), - // The pointer to the nested array of the first item - Value::from(10_usize), - Value::from(3_usize), - // The pointer to the nested array of the second item + // The pointer to the nested reference of the first item Value::from(12_usize), + Value::from(3_usize), + // The pointer to the nested reference of the second item + Value::from(16_usize), Value::from(6_usize), // The nested array of the first item Value::from(1_usize), Value::from(2_usize), + // The nested reference of the first item + Value::from(10_usize), + Value::from(1_usize), // The nested array of the second item Value::from(4_usize), Value::from(5_usize), + // The nested reference of the second item + Value::from(14_usize), + Value::from(1_usize), ] ); } @@ -358,35 +441,31 @@ mod tests { Value::from(5_usize), Value::from(6_usize), ]; - let array_param = BrilligParameter::Array( vec![ - BrilligParameter::Simple, BrilligParameter::Array(vec![BrilligParameter::Simple], 2), + BrilligParameter::Simple, ], 2, ); - let arguments = vec![array_param.clone()]; let returns = vec![array_param]; let mut context = create_context(); // Allocate the parameter - let array_pointer = context.allocate_register(); + let brillig_array = BrilligArray { + pointer: context.allocate_register(), + size: 2, + rc: context.allocate_register(), + }; - context.return_instruction(&[array_pointer]); + context.return_instruction(&brillig_array.extract_registers()); let bytecode = create_entry_point_bytecode(context, arguments, returns).byte_code; let vm = create_and_run_vm(flattened_array.clone(), vec![Value::from(0_usize)], &bytecode); let memory = vm.get_memory(); - assert_eq!( - vm.get_registers().get(RegisterIndex(0)), - // The returned value will be past the original array and the deflattened array - Value::from(flattened_array.len() + (flattened_array.len() + 2)), - ); - assert_eq!( memory, &vec![ @@ -397,19 +476,25 @@ mod tests { Value::from(4_usize), Value::from(5_usize), Value::from(6_usize), - // The pointer to the nested array of the first item - Value::from(1_usize), - Value::from(10_usize), - // The pointer to the nested array of the second item - Value::from(4_usize), + // The pointer to the nested reference of the first item Value::from(12_usize), + Value::from(3_usize), + // The pointer to the nested reference of the second item + Value::from(16_usize), + Value::from(6_usize), // The nested array of the first item + Value::from(1_usize), Value::from(2_usize), - Value::from(3_usize), + // The nested reference of the first item + Value::from(10_usize), + Value::from(1_usize), // The nested array of the second item + Value::from(4_usize), Value::from(5_usize), - Value::from(6_usize), - // The values flattened again + // The nested reference of the second item + Value::from(14_usize), + Value::from(1_usize), + // The original flattened again Value::from(1_usize), Value::from(2_usize), Value::from(3_usize), @@ -418,5 +503,6 @@ mod tests { Value::from(6_usize), ] ); + assert_eq!(vm.get_registers().get(RegisterIndex(0)), 18_usize.into()); } } diff --git a/compiler/noirc_evaluator/src/errors.rs b/compiler/noirc_evaluator/src/errors.rs index 42672d4d0a..42818e8b19 100644 --- a/compiler/noirc_evaluator/src/errors.rs +++ b/compiler/noirc_evaluator/src/errors.rs @@ -26,7 +26,7 @@ pub enum RuntimeError { }, #[error(transparent)] InternalError(#[from] InternalError), - #[error("Index out of bounds, array has size {index:?}, but index was {array_size:?}")] + #[error("Index out of bounds, array has size {array_size}, but index was {index}")] IndexOutOfBounds { index: usize, array_size: usize, call_stack: CallStack }, #[error("Range constraint of {num_bits} bits is too large for the Field size")] InvalidRangeConstraint { num_bits: u32, call_stack: CallStack }, diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index c4b19379ec..712913841f 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -130,8 +130,8 @@ impl AcirContext { } /// Adds a constant to the context and assigns a Variable to represent it - pub(crate) fn add_constant(&mut self, constant: FieldElement) -> AcirVar { - let constant_data = AcirVarData::Const(constant); + pub(crate) fn add_constant(&mut self, constant: impl Into) -> AcirVar { + let constant_data = AcirVarData::Const(constant.into()); self.add_data(constant_data) } @@ -353,7 +353,7 @@ impl AcirContext { // Check to see if equality can be determined at compile-time. if diff_expr.is_const() { - return Ok(self.add_constant(diff_expr.is_zero().into())); + return Ok(self.add_constant(diff_expr.is_zero())); } let is_equal_witness = self.acir_ir.is_equal(&lhs_expr, &rhs_expr); @@ -380,9 +380,15 @@ impl AcirContext { rhs: AcirVar, typ: AcirType, ) -> Result { - let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)]; - let outputs = self.black_box_function(BlackBoxFunc::AND, inputs, 1)?; - Ok(outputs[0]) + let bit_size = typ.bit_size(); + if bit_size == 1 { + // Operands are booleans. + self.mul_var(lhs, rhs) + } else { + let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)]; + let outputs = self.black_box_function(BlackBoxFunc::AND, inputs, 1)?; + Ok(outputs[0]) + } } /// Returns an `AcirVar` that is the OR result of `lhs` & `rhs`. @@ -404,7 +410,7 @@ impl AcirContext { // max - ((max - a) AND (max -b)) // Subtracting from max flips the bits, so this is effectively: // (NOT a) NAND (NOT b) - let max = self.add_constant(FieldElement::from((1_u128 << bit_size) - 1)); + let max = self.add_constant((1_u128 << bit_size) - 1); let a = self.sub_var(max, lhs)?; let b = self.sub_var(max, rhs)?; let inputs = vec![AcirValue::Var(a, typ.clone()), AcirValue::Var(b, typ)]; @@ -547,7 +553,7 @@ impl AcirContext { pub(crate) fn not_var(&mut self, x: AcirVar, typ: AcirType) -> Result { let bit_size = typ.bit_size(); // Subtracting from max flips the bits - let max = self.add_constant(FieldElement::from((1_u128 << bit_size) - 1)); + let max = self.add_constant((1_u128 << bit_size) - 1); self.sub_var(max, x) } @@ -574,8 +580,8 @@ impl AcirContext { let quotient = lhs_const.to_u128() / rhs_const.to_u128(); let remainder = lhs_const.to_u128() - quotient * rhs_const.to_u128(); - let quotient_var = self.add_constant(FieldElement::from(quotient)); - let remainder_var = self.add_constant(FieldElement::from(remainder)); + let quotient_var = self.add_constant(quotient); + let remainder_var = self.add_constant(remainder); return Ok((quotient_var, remainder_var)); } @@ -772,7 +778,7 @@ impl AcirContext { // witness = lhs_offset + r assert!(bits + r_bit_size < FieldElement::max_num_bits()); //we need to ensure lhs_offset + r does not overflow - let r_var = self.add_constant(r.into()); + let r_var = self.add_constant(r); let aor = self.add_var(lhs_offset, r_var)?; // lhs_offset<=rhs_offset <=> lhs_offset + r < rhs_offset + r = 2^bit_size <=> witness < 2^bit_size self.range_constrain_var(aor, &NumericType::Unsigned { bit_size }, None)?; @@ -871,7 +877,8 @@ impl AcirContext { /// Converts the `AcirVar` to a `Witness` if it hasn't been already, and appends it to the /// `GeneratedAcir`'s return witnesses. pub(crate) fn return_var(&mut self, acir_var: AcirVar) -> Result<(), InternalError> { - let witness = self.var_to_witness(acir_var)?; + let return_var = self.get_or_create_witness_var(acir_var)?; + let witness = self.var_to_witness(return_var)?; self.acir_ir.push_return_witness(witness); Ok(()) } @@ -920,7 +927,7 @@ impl AcirContext { ) -> Result { // 2^{rhs} let divisor = - self.add_constant(FieldElement::from(2_i128).pow(&FieldElement::from(rhs as i128))); + self.add_constant(FieldElement::from(2_u128).pow(&FieldElement::from(rhs as u128))); let one = self.add_constant(FieldElement::one()); // Computes lhs = 2^{rhs} * q + r @@ -931,7 +938,7 @@ impl AcirContext { /// Returns an `AcirVar` which will be `1` if lhs >= rhs /// and `0` otherwise. - fn more_than_eq_var( + pub(crate) fn more_than_eq_var( &mut self, lhs: AcirVar, rhs: AcirVar, @@ -1144,10 +1151,7 @@ impl AcirContext { // `Intrinsic::ToRadix` returns slices which are represented // by tuples with the structure (length, slice contents) Ok(vec![ - AcirValue::Var( - self.add_constant(FieldElement::from(limb_vars.len() as u128)), - AcirType::field(), - ), + AcirValue::Var(self.add_constant(limb_vars.len()), AcirType::field()), AcirValue::Array(limb_vars.into()), ]) } @@ -1160,7 +1164,7 @@ impl AcirContext { limb_count_var: AcirVar, result_element_type: AcirType, ) -> Result, RuntimeError> { - let two_var = self.add_constant(FieldElement::from(2_u128)); + let two_var = self.add_constant(2_u128); self.radix_decompose(endian, input_var, two_var, limb_count_var, result_element_type) } @@ -1268,7 +1272,7 @@ impl AcirContext { AcirValue::DynamicArray(AcirDynamicArray { block_id, len, .. }) => { for i in 0..len { // We generate witnesses corresponding to the array values - let index_var = self.add_constant(FieldElement::from(i as u128)); + let index_var = self.add_constant(i); let value_read_var = self.read_from_memory(block_id, &index_var)?; let value_read = AcirValue::Var(value_read_var, AcirType::field()); @@ -1422,7 +1426,8 @@ impl AcirContext { index: &AcirVar, ) -> Result { // Fetch the witness corresponding to the index - let index_witness = self.var_to_witness(*index)?; + let index_var = self.get_or_create_witness_var(*index)?; + let index_witness = self.var_to_witness(index_var)?; // Create a Variable to hold the result of the read and extract the corresponding Witness let value_read_var = self.add_variable(); @@ -1443,11 +1448,12 @@ impl AcirContext { value: &AcirVar, ) -> Result<(), InternalError> { // Fetch the witness corresponding to the index - // - let index_witness = self.var_to_witness(*index)?; + let index_var = self.get_or_create_witness_var(*index)?; + let index_witness = self.var_to_witness(index_var)?; // Fetch the witness corresponding to the value to be written - let value_write_witness = self.var_to_witness(*value)?; + let value_write_var = self.get_or_create_witness_var(*value)?; + let value_write_witness = self.var_to_witness(value_write_var)?; // Add the memory write operation to the list of opcodes let op = MemOp::write_to_mem_index(index_witness.into(), value_write_witness.into()); @@ -1489,6 +1495,7 @@ impl AcirContext { ) -> Result<(), InternalError> { match input { AcirValue::Var(var, _) => { + let var = self.get_or_create_witness_var(var)?; witnesses.push(self.var_to_witness(var)?); } AcirValue::Array(values) => { diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 2f58957c73..d73bb514e0 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -5,6 +5,7 @@ use std::collections::HashSet; use std::fmt::Debug; use self::acir_ir::acir_variable::{AcirContext, AcirType, AcirVar}; +use super::function_builder::data_bus::DataBus; use super::ir::dfg::CallStack; use super::{ ir::{ @@ -90,6 +91,8 @@ struct Context { /// Maps SSA array values to their slice size and any nested slices internal to the parent slice. /// This enables us to maintain the slice structure of a slice when performing an array get. slice_sizes: HashMap, Vec>, + + data_bus: DataBus, } #[derive(Clone)] @@ -101,14 +104,16 @@ pub(crate) struct AcirDynamicArray { len: usize, /// Identification for the ACIR dynamic array /// inner element type sizes array - element_type_sizes: BlockId, + element_type_sizes: Option, } impl Debug for AcirDynamicArray { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!( f, "id: {}, len: {}, element_type_sizes: {:?}", - self.block_id.0, self.len, self.element_type_sizes.0 + self.block_id.0, + self.len, + self.element_type_sizes.map(|block_id| block_id.0) ) } } @@ -131,6 +136,16 @@ impl AcirValue { } } + fn borrow_var(&self) -> Result { + match self { + AcirValue::Var(var, _) => Ok(*var), + AcirValue::DynamicArray(_) | AcirValue::Array(_) => Err(InternalError::General { + message: "Called AcirValue::borrow_var on an array".to_string(), + call_stack: CallStack::new(), + }), + } + } + fn flatten(self) -> Vec<(AcirVar, AcirType)> { match self { AcirValue::Var(var, typ) => vec![(var, typ)], @@ -187,6 +202,7 @@ impl Context { internal_mem_block_lengths: HashMap::default(), max_block_id: 0, slice_sizes: HashMap::default(), + data_bus: DataBus::default(), } } @@ -214,6 +230,8 @@ impl Context { let dfg = &main_func.dfg; let entry_block = &dfg[main_func.entry_block()]; let input_witness = self.convert_ssa_block_params(entry_block.parameters(), dfg)?; + + self.data_bus = dfg.data_bus.to_owned(); let mut warnings = Vec::new(); for instruction_id in entry_block.instructions() { warnings.extend(self.convert_ssa_instruction( @@ -439,8 +457,7 @@ impl Context { let mut read_dynamic_array_index = |block_id: BlockId, array_index: usize| -> Result { - let index_var = - self.acir_context.add_constant(FieldElement::from(array_index as u128)); + let index_var = self.acir_context.add_constant(array_index); self.acir_context.read_from_memory(block_id, &index_var) }; @@ -563,6 +580,9 @@ impl Context { Instruction::Load { .. } => { unreachable!("Expected all load instructions to be removed before acir_gen") } + Instruction::IncrementRc { .. } => { + // Do nothing. Only Brillig needs to worry about reference counted arrays + } Instruction::RangeCheck { value, max_bit_size, assert_message } => { let acir_var = self.convert_numeric_value(*value, dfg)?; self.acir_context.range_constrain_var( @@ -847,7 +867,7 @@ impl Context { ); let values = try_vecmap(0..*len, |i| { - let index_var = self.acir_context.add_constant(FieldElement::from(i as u128)); + let index_var = self.acir_context.add_constant(i); let read = self.acir_context.read_from_memory(*block_id, &index_var)?; Ok::(AcirValue::Var(read, AcirType::field())) @@ -878,10 +898,26 @@ impl Context { dfg: &DataFlowGraph, ) -> Result { let (array_id, _, block_id) = self.check_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 { + if self.data_bus.call_data_map.contains_key(&array_id) { + // TODO: the block_id of call-data must be notified to the backend + // TODO: should we do the same for return-data? + 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 bus_index = self.acir_context.add_constant(FieldElement::from( + self.data_bus.call_data_map[&array_id] as i128, + )); + let new_index = self.acir_context.add_var(offset, bus_index)?; + return self.array_get(instruction, call_data, new_index, dfg); + } + } + let value = if !res_typ.contains_slice_element() { self.array_get_value(&res_typ, block_id, &mut var_index, &[])? } else { @@ -892,7 +928,7 @@ impl Context { // The first max size is going to be the length of the parent slice // As we are fetching from the parent slice we just want its internal - // slize sizes. + // slice sizes. let slice_sizes = slice_sizes[1..].to_vec(); let value = self.array_get_value(&res_typ, block_id, &mut var_index, &slice_sizes)?; @@ -921,7 +957,7 @@ impl Context { // Read the value from the array at the specified index let read = self.acir_context.read_from_memory(block_id, var_index)?; - // Incremement the var_index in case of a nested array + // Increment the var_index in case of a nested array *var_index = self.acir_context.add_var(*var_index, one)?; let typ = AcirType::NumericType(numeric_type); @@ -1017,7 +1053,7 @@ impl Context { self.copy_dynamic_array(block_id, result_block_id, array_len)?; } - self.array_set_value(store_value, result_block_id, &mut var_index)?; + self.array_set_value(&store_value, result_block_id, &mut var_index)?; // Set new resulting array to have the same slice sizes as the instruction input if let Type::Slice(element_types) = &array_typ { @@ -1036,8 +1072,11 @@ impl Context { } } - let element_type_sizes = - self.init_element_type_sizes_array(&array_typ, array_id, None, dfg)?; + let element_type_sizes = if !can_omit_element_sizes_array(&array_typ) { + Some(self.init_element_type_sizes_array(&array_typ, array_id, None, dfg)?) + } else { + None + }; let result_value = AcirValue::DynamicArray(AcirDynamicArray { block_id: result_block_id, len: array_len, @@ -1049,7 +1088,7 @@ impl Context { fn array_set_value( &mut self, - value: AcirValue, + value: &AcirValue, block_id: BlockId, var_index: &mut AcirVar, ) -> Result<(), RuntimeError> { @@ -1057,8 +1096,8 @@ impl Context { match value { AcirValue::Var(store_var, _) => { // Write the new value into the new array at the specified index - self.acir_context.write_to_memory(block_id, var_index, &store_var)?; - // Incremement the var_index in case of a nested array + self.acir_context.write_to_memory(block_id, var_index, store_var)?; + // Increment the var_index in case of a nested array *var_index = self.acir_context.add_var(*var_index, one)?; } AcirValue::Array(values) => { @@ -1067,13 +1106,13 @@ impl Context { } } AcirValue::DynamicArray(AcirDynamicArray { block_id: inner_block_id, len, .. }) => { - let values = try_vecmap(0..len, |i| { - let index_var = self.acir_context.add_constant(FieldElement::from(i as u128)); + let values = try_vecmap(0..*len, |i| { + let index_var = self.acir_context.add_constant(i); - let read = self.acir_context.read_from_memory(inner_block_id, &index_var)?; + let read = self.acir_context.read_from_memory(*inner_block_id, &index_var)?; Ok::(AcirValue::Var(read, AcirType::field())) })?; - self.array_set_value(AcirValue::Array(values.into()), block_id, var_index)?; + self.array_set_value(&AcirValue::Array(values.into()), block_id, var_index)?; } } Ok(()) @@ -1162,27 +1201,29 @@ impl Context { element_type_sizes: inner_elem_type_sizes, .. }) => { - if self.initialized_arrays.contains(&inner_elem_type_sizes) { - let type_sizes_array_len = self.internal_mem_block_lengths.get(&inner_elem_type_sizes).copied().ok_or_else(|| - InternalError::General { - message: format!("Array {array_id}'s inner element type sizes array does not have a tracked length"), + if let Some(inner_elem_type_sizes) = inner_elem_type_sizes { + if self.initialized_arrays.contains(&inner_elem_type_sizes) { + let type_sizes_array_len = self.internal_mem_block_lengths.get(&inner_elem_type_sizes).copied().ok_or_else(|| + InternalError::General { + message: format!("Array {array_id}'s inner element type sizes array does not have a tracked length"), + call_stack: self.acir_context.get_call_stack(), + } + )?; + self.copy_dynamic_array( + inner_elem_type_sizes, + element_type_sizes, + type_sizes_array_len, + )?; + self.internal_mem_block_lengths + .insert(element_type_sizes, type_sizes_array_len); + return Ok(element_type_sizes); + } else { + return Err(InternalError::General { + message: format!("Array {array_id}'s inner element type sizes array should be initialized"), call_stack: self.acir_context.get_call_stack(), } - )?; - self.copy_dynamic_array( - inner_elem_type_sizes, - element_type_sizes, - type_sizes_array_len, - )?; - self.internal_mem_block_lengths - .insert(element_type_sizes, type_sizes_array_len); - return Ok(element_type_sizes); - } else { - return Err(InternalError::General { - message: format!("Array {array_id}'s inner element type sizes array should be initialized"), - call_stack: self.acir_context.get_call_stack(), + .into()); } - .into()); } } AcirValue::Array(values) => { @@ -1225,7 +1266,7 @@ impl Context { // The final array should will the flattened index at each outer array index let init_values = vecmap(flat_elem_type_sizes, |type_size| { - let var = self.acir_context.add_constant(FieldElement::from(type_size as u128)); + let var = self.acir_context.add_constant(type_size); AcirValue::Var(var, AcirType::field()) }); let element_type_sizes_len = init_values.len(); @@ -1282,7 +1323,7 @@ impl Context { array_len: usize, ) -> Result<(), RuntimeError> { let init_values = try_vecmap(0..array_len, |i| { - let index_var = self.acir_context.add_constant(FieldElement::from(i as u128)); + let index_var = self.acir_context.add_constant(i); let read = self.acir_context.read_from_memory(source, &index_var)?; Ok::(AcirValue::Var(read, AcirType::field())) @@ -1298,15 +1339,19 @@ impl Context { var_index: AcirVar, dfg: &DataFlowGraph, ) -> Result { - let element_type_sizes = - self.init_element_type_sizes_array(array_typ, array_id, None, dfg)?; + if !can_omit_element_sizes_array(array_typ) { + let element_type_sizes = + self.init_element_type_sizes_array(array_typ, array_id, None, dfg)?; - let predicate_index = - self.acir_context.mul_var(var_index, self.current_side_effects_enabled_var)?; - let flat_element_size_var = - self.acir_context.read_from_memory(element_type_sizes, &predicate_index)?; + let predicate_index = + self.acir_context.mul_var(var_index, self.current_side_effects_enabled_var)?; - Ok(flat_element_size_var) + self.acir_context + .read_from_memory(element_type_sizes, &predicate_index) + .map_err(RuntimeError::from) + } else { + Ok(var_index) + } } fn flattened_slice_size(&mut self, array_id: ValueId, dfg: &DataFlowGraph) -> usize { @@ -1565,7 +1610,7 @@ impl Context { (_, Type::Function) | (Type::Function, _) => { unreachable!("all functions should be inlined") } - (_, Type::Reference) | (Type::Reference, _) => { + (_, Type::Reference(_)) | (Type::Reference(_), _) => { unreachable!("References are invalid in binary operations") } (_, Type::Array(..)) | (Type::Array(..), _) => { @@ -1639,8 +1684,7 @@ impl Context { ) { // Subtractions must first have the integer modulus added before truncation can be // applied. This is done in order to prevent underflow. - let integer_modulus = - self.acir_context.add_constant(FieldElement::from(2_u128.pow(bit_size))); + let integer_modulus = self.acir_context.add_constant(2_u128.pow(bit_size)); var = self.acir_context.add_var(var, integer_modulus)?; } } @@ -1746,197 +1790,579 @@ impl Context { Intrinsic::ArrayLen => { let len = match self.convert_value(arguments[0], dfg) { AcirValue::Var(_, _) => unreachable!("Non-array passed to array.len() method"), - AcirValue::Array(values) => (values.len() as u128).into(), - AcirValue::DynamicArray(array) => (array.len as u128).into(), + AcirValue::Array(values) => values.len(), + AcirValue::DynamicArray(array) => array.len, }; Ok(vec![AcirValue::Var(self.acir_context.add_constant(len), AcirType::field())]) } Intrinsic::SlicePushBack => { + // arguments = [slice_length, slice_contents, ...elements_to_push] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; - let (array_id, array_typ, _) = + let (slice_contents, slice_typ, _) = self.check_array_is_initialized(arguments[1], dfg)?; - let slice = self.convert_value(arguments[1], dfg); + let slice = self.convert_value(slice_contents, dfg); - // TODO(#3364): make sure that we have handled nested struct inputs - let element = self.convert_value(arguments[2], dfg); - let one = self.acir_context.add_constant(FieldElement::one()); - let new_slice_length = self.acir_context.add_var(slice_length, one)?; + let mut new_elem_size = Self::flattened_value_size(&slice); - // We attach the element no matter what in case len == capacity, as otherwise we - // may get an out of bounds error. let mut new_slice = Vector::new(); - self.slice_intrinsic_input(&mut new_slice, slice.clone())?; - new_slice.push_back(element.clone()); + self.slice_intrinsic_input(&mut new_slice, slice)?; + + let elements_to_push = &arguments[2..]; + // We only fill internal slices for nested slices (a slice inside of a slice). + // So we must directly push back elements for slices which are not a nested slice. + if !slice_typ.is_nested_slice() { + for elem in elements_to_push { + let element = self.convert_value(*elem, dfg); + + new_elem_size += Self::flattened_value_size(&element); + new_slice.push_back(element); + } + } + + // Increase the slice length by one to enable accessing more elements in the slice. + let one = self.acir_context.add_constant(FieldElement::one()); + let new_slice_length = self.acir_context.add_var(slice_length, one)?; - // TODO(#3364): This works for non-nested outputs - let len = Self::flattened_value_size(&slice); - let new_elem_size = Self::flattened_value_size(&element); let new_slice_val = AcirValue::Array(new_slice); let result_block_id = self.block_id(&result_ids[1]); - self.initialize_array( - result_block_id, - len + new_elem_size, - Some(new_slice_val.clone()), - )?; + self.initialize_array(result_block_id, new_elem_size, Some(new_slice_val.clone()))?; + // The previous slice length represents the index we want to write into. let mut var_index = slice_length; - self.array_set_value(element, result_block_id, &mut var_index)?; + // Dynamic arrays are represented as flat memory. We must flatten the user facing index + // to a flattened index that matches the complex slice structure. + if slice_typ.is_nested_slice() { + let element_size = slice_typ.element_size(); + + // Multiply the element size against the var index before fetching the flattened index + // This operation makes sure our user-facing slice index matches the strategy for indexing in SSA, + // which is how `get_flattened_index` expects its index input. + let element_size_var = self.acir_context.add_constant(element_size); + var_index = self.acir_context.mul_var(slice_length, element_size_var)?; + var_index = + self.get_flattened_index(&slice_typ, slice_contents, var_index, dfg)?; + } - let result = AcirValue::DynamicArray(AcirDynamicArray { - block_id: result_block_id, - len: len + new_elem_size, - element_type_sizes: self.init_element_type_sizes_array( - &array_typ, - array_id, + // Write the elements we wish to push back directly. + // The slice's underlying array value should already be filled with dummy data + // to enable this write to be within bounds. + // The dummy data is either attached during SSA gen or in this match case for non-nested slices. + // These values can then be accessed due to the increased dynamic slice length. + for elem in elements_to_push { + let element = self.convert_value(*elem, dfg); + self.array_set_value(&element, result_block_id, &mut var_index)?; + } + + let element_type_sizes = if !can_omit_element_sizes_array(&slice_typ) { + Some(self.init_element_type_sizes_array( + &slice_typ, + slice_contents, Some(new_slice_val), dfg, - )?, + )?) + } else { + None + }; + let result = AcirValue::DynamicArray(AcirDynamicArray { + block_id: result_block_id, + len: new_elem_size, + element_type_sizes, }); Ok(vec![AcirValue::Var(new_slice_length, AcirType::field()), result]) } Intrinsic::SlicePushFront => { + // arguments = [slice_length, slice_contents, ...elements_to_push] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; - let slice: AcirValue = self.convert_value(arguments[1], dfg); - // TODO(#3364): make sure that we have handled nested struct inputs - let element = self.convert_value(arguments[2], dfg); + let (slice_contents, slice_typ, _) = + self.check_array_is_initialized(arguments[1], dfg)?; + let slice: AcirValue = self.convert_value(slice_contents, dfg); + + let mut new_slice_size = Self::flattened_value_size(&slice); + + // Increase the slice length by one to enable accessing more elements in the slice. let one = self.acir_context.add_constant(FieldElement::one()); let new_slice_length = self.acir_context.add_var(slice_length, one)?; let mut new_slice = Vector::new(); self.slice_intrinsic_input(&mut new_slice, slice)?; - new_slice.push_front(element); - Ok(vec![ - AcirValue::Var(new_slice_length, AcirType::field()), - AcirValue::Array(new_slice), - ]) + let elements_to_push = &arguments[2..]; + let mut elem_size = 0; + // We only fill internal slices for nested slices (a slice inside of a slice). + // So we must directly push front elements for slices which are not a nested slice. + if !slice_typ.is_nested_slice() { + for elem in elements_to_push.iter().rev() { + let element = self.convert_value(*elem, dfg); + + elem_size += Self::flattened_value_size(&element); + new_slice.push_front(element); + } + new_slice_size += elem_size; + } else { + // We have already filled the appropriate dummy values for nested slice during SSA gen. + // We need to account for that we do not go out of bounds by removing dummy data as we + // push elements to the front of our slice. + // Using this strategy we are able to avoid dynamic writes like we do for a SlicePushBack. + for elem in elements_to_push.iter().rev() { + let element = self.convert_value(*elem, dfg); + + let elem_size = Self::flattened_value_size(&element); + // Have to pop based off of the flattened value size as we read the + // slice intrinsic as a flat list of AcirValue::Var + for _ in 0..elem_size { + new_slice.pop_back(); + } + new_slice.push_front(element); + } + } + + let new_slice_val = AcirValue::Array(new_slice.clone()); + + let result_block_id = self.block_id(&result_ids[1]); + self.initialize_array( + result_block_id, + new_slice_size, + Some(new_slice_val.clone()), + )?; + + let element_type_sizes = if !can_omit_element_sizes_array(&slice_typ) { + Some(self.init_element_type_sizes_array( + &slice_typ, + slice_contents, + Some(new_slice_val), + dfg, + )?) + } else { + None + }; + let result = AcirValue::DynamicArray(AcirDynamicArray { + block_id: result_block_id, + len: new_slice_size, + element_type_sizes, + }); + + Ok(vec![AcirValue::Var(new_slice_length, AcirType::field()), result]) } Intrinsic::SlicePopBack => { + // arguments = [slice_length, slice_contents] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; - let slice = self.convert_value(arguments[1], dfg); let one = self.acir_context.add_constant(FieldElement::one()); let new_slice_length = self.acir_context.sub_var(slice_length, one)?; - - let (_, _, block_id) = self.check_array_is_initialized(arguments[1], dfg)?; + // For a pop back operation we want to fetch from the `length - 1` as this is the + // last valid index that can be accessed in a slice. After the pop back operation + // the elements stored at that index will no longer be able to be accessed. let mut var_index = new_slice_length; - let elem = self.array_get_value( - &dfg.type_of_value(result_ids[2]), - block_id, - &mut var_index, - &[], - )?; - // TODO(#3364): make sure that we have handled nested struct inputs + let (slice_contents, slice_typ, block_id) = + self.check_array_is_initialized(arguments[1], dfg)?; + let slice = self.convert_value(slice_contents, dfg); + + let element_size = slice_typ.element_size(); + + let mut popped_elements = Vec::new(); + // Fetch the values we are popping off of the slice. + // In the case of non-nested slice the logic is simple as we do not + // need to account for the internal slice sizes or flattening the index. + // + // The pop back operation results are of the format [slice length, slice contents, popped elements]. + // Thus, we look at the result ids at index 2 and onwards to determine the type of each popped element. + if !slice_typ.is_nested_slice() { + for res in &result_ids[2..] { + let elem = self.array_get_value( + &dfg.type_of_value(*res), + block_id, + &mut var_index, + &[], + )?; + popped_elements.push(elem); + } + } else { + // Fetch the slice sizes of the nested slice. + let slice_sizes = self.slice_sizes.get(&slice_contents); + let mut slice_sizes = + slice_sizes.expect("ICE: should have slice sizes").clone(); + // We want to remove the parent size as we are fetching the child + slice_sizes.remove(0); + + // Multiply the element size against the var index before fetching the flattened index + // This operation makes sure our user-facing slice index matches the strategy for indexing in SSA, + // which is how `get_flattened_index` expects its index input. + let element_size_var = self.acir_context.add_constant(element_size); + // We want to use an index one less than the slice length + var_index = self.acir_context.mul_var(var_index, element_size_var)?; + var_index = + self.get_flattened_index(&slice_typ, slice_contents, var_index, dfg)?; + + for res in &result_ids[2..] { + let elem = self.array_get_value( + &dfg.type_of_value(*res), + block_id, + &mut var_index, + &slice_sizes, + )?; + popped_elements.push(elem); + } + } + let mut new_slice = Vector::new(); self.slice_intrinsic_input(&mut new_slice, slice)?; - Ok(vec![ + let mut results = vec![ AcirValue::Var(new_slice_length, AcirType::field()), AcirValue::Array(new_slice), - elem, - ]) + ]; + results.append(&mut popped_elements); + + Ok(results) } Intrinsic::SlicePopFront => { + // arguments = [slice_length, slice_contents] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; - let slice = self.convert_value(arguments[1], dfg); + + let (slice_contents, slice_typ, block_id) = + self.check_array_is_initialized(arguments[1], dfg)?; + let slice = self.convert_value(slice_contents, dfg); let one = self.acir_context.add_constant(FieldElement::one()); let new_slice_length = self.acir_context.sub_var(slice_length, one)?; let mut new_slice = Vector::new(); self.slice_intrinsic_input(&mut new_slice, slice)?; - // TODO(#3364): make sure that we have handled nested struct inputs - let elem = new_slice - .pop_front() - .expect("There are no elements in this slice to be removed"); - Ok(vec![ - elem, - AcirValue::Var(new_slice_length, AcirType::field()), - AcirValue::Array(new_slice), - ]) + let element_size = slice_typ.element_size(); + + let mut popped_elements: Vec = Vec::new(); + let mut popped_elements_size = 0; + let mut var_index = self.acir_context.add_constant(FieldElement::zero()); + // Fetch the values we are popping off of the slice. + // In the case of non-nested slice the logic is simple as we do not + // need to account for the internal slice sizes or flattening the index. + // + // The pop front operation results are of the format [popped elements, slice length, slice contents]. + // Thus, we look at the result ids up to the element size to determine the type of each popped element. + if !slice_typ.is_nested_slice() { + for res in &result_ids[..element_size] { + let element = self.array_get_value( + &dfg.type_of_value(*res), + block_id, + &mut var_index, + &[], + )?; + let elem_size = Self::flattened_value_size(&element); + popped_elements_size += elem_size; + popped_elements.push(element); + } + } else { + let slice_sizes = self.slice_sizes.get(&slice_contents); + let mut slice_sizes = + slice_sizes.expect("ICE: should have slice sizes").clone(); + // We want to remove the parent size as we are fetching the child + slice_sizes.remove(0); + + for res in &result_ids[..element_size] { + let element = self.array_get_value( + &dfg.type_of_value(*res), + block_id, + &mut var_index, + &slice_sizes, + )?; + let elem_size = Self::flattened_value_size(&element); + popped_elements_size += elem_size; + popped_elements.push(element); + } + } + // It is expected that the `popped_elements_size` is the flattened size of the elements, + // as the input slice should be a dynamic array which is represented by flat memory. + new_slice = new_slice.slice(popped_elements_size..); + + popped_elements.push(AcirValue::Var(new_slice_length, AcirType::field())); + popped_elements.push(AcirValue::Array(new_slice)); + + Ok(popped_elements) } Intrinsic::SliceInsert => { - // Slice insert with a constant index + // arguments = [slice_length, slice_contents, insert_index, ...elements_to_insert] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; - let slice = self.convert_value(arguments[1], dfg); - let index = self.convert_value(arguments[2], dfg).into_var()?; - let element = self.convert_value(arguments[3], dfg); + + let (slice_contents, slice_typ, block_id) = + self.check_array_is_initialized(arguments[1], dfg)?; + + let slice = self.convert_value(slice_contents, dfg); + let insert_index = self.convert_value(arguments[2], dfg).into_var()?; let one = self.acir_context.add_constant(FieldElement::one()); let new_slice_length = self.acir_context.add_var(slice_length, one)?; - // TODO(#2462): Slice insert is a little less obvious on how to implement due to the case - // of having a dynamic index - // The slice insert logic will need a more involved codegen - let index = self.acir_context.var_to_expression(index)?.to_const(); - let index = index - .expect("ICE: slice length should be fully tracked and constant by ACIR gen"); - let index = index.to_u128() as usize; + let slice_size = Self::flattened_value_size(&slice); + + // Fetch the flattened index from the user provided index argument. + let element_size = slice_typ.element_size(); + let element_size_var = self.acir_context.add_constant(element_size); + let flat_insert_index = + self.acir_context.mul_var(insert_index, element_size_var)?; + let flat_user_index = + self.get_flattened_index(&slice_typ, slice_contents, flat_insert_index, dfg)?; + + let elements_to_insert = &arguments[3..]; + // Determine the elements we need to write into our resulting dynamic array. + // We need to a fully flat list of AcirVar's as a dynamic array is represented with flat memory. + let mut inner_elem_size_usize = 0; + let mut flattened_elements = Vec::new(); + for elem in elements_to_insert { + let element = self.convert_value(*elem, dfg); + let elem_size = Self::flattened_value_size(&element); + inner_elem_size_usize += elem_size; + let mut flat_elem = element.flatten().into_iter().map(|(var, _)| var).collect(); + flattened_elements.append(&mut flat_elem); + } + let inner_elem_size = self.acir_context.add_constant(inner_elem_size_usize); + // Set the maximum flattened index at which a new element should be inserted. + let max_flat_user_index = + self.acir_context.add_var(flat_user_index, inner_elem_size)?; + + // Go through the entire slice argument and determine what value should be written to the new slice. + // 1. If we are below the starting insertion index we should insert the value that was already + // in the original slice. + // 2. If we are above the starting insertion index but below the max insertion index we should insert + // the flattened element arguments. + // 3. If we are above the max insertion index we should insert the previous value from the original slice, + // as during an insertion we want to shift all elements after the insertion up an index. + let result_block_id = self.block_id(&result_ids[1]); + self.initialize_array(result_block_id, slice_size, None)?; + let mut current_insert_index = 0; + for i in 0..slice_size { + let current_index = self.acir_context.add_constant(i); + + // Check that we are above the lower bound of the insertion index + let greater_eq_than_idx = self.acir_context.more_than_eq_var( + current_index, + flat_user_index, + 64, + self.current_side_effects_enabled_var, + )?; + // Check that we are below the upper bound of the insertion index + let less_than_idx = self.acir_context.less_than_var( + current_index, + max_flat_user_index, + 64, + self.current_side_effects_enabled_var, + )?; + + // Read from the original slice the value we want to insert into our new slice. + // We need to make sure that we read the previous element when our current index is greater than insertion index. + // If the index for the previous element is out of the array bounds we can avoid the check for whether + // the current index is over the insertion index. + let shifted_index = if i < inner_elem_size_usize { + current_index + } else { + let index_minus_elem_size = + self.acir_context.add_constant(i - inner_elem_size_usize); - let mut new_slice = Vector::new(); - self.slice_intrinsic_input(&mut new_slice, slice)?; + let use_shifted_index_pred = self + .acir_context + .mul_var(index_minus_elem_size, greater_eq_than_idx)?; - // We do not return an index out of bounds error directly here - // as the length of the slice is dynamic, and length of `new_slice` - // represents the capacity of the slice, not the actual length. - // - // Constraints should be generated during SSA gen to tell the user - // they are attempting to insert at too large of an index. - // This check prevents a panic inside of the im::Vector insert method. - if index <= new_slice.len() { - // TODO(#3364): make sure that we have handled nested struct inputs - new_slice.insert(index, element); + let not_pred = self.acir_context.sub_var(one, greater_eq_than_idx)?; + let use_current_index_pred = + self.acir_context.mul_var(not_pred, current_index)?; + + self.acir_context.add_var(use_shifted_index_pred, use_current_index_pred)? + }; + + let value_shifted_index = + self.acir_context.read_from_memory(block_id, &shifted_index)?; + + // Final predicate to determine whether we are within the insertion bounds + let should_insert_value_pred = + self.acir_context.mul_var(greater_eq_than_idx, less_than_idx)?; + let insert_value_pred = self.acir_context.mul_var( + flattened_elements[current_insert_index], + should_insert_value_pred, + )?; + + let not_pred = self.acir_context.sub_var(one, should_insert_value_pred)?; + let shifted_value_pred = + self.acir_context.mul_var(not_pred, value_shifted_index)?; + + let new_value = + self.acir_context.add_var(insert_value_pred, shifted_value_pred)?; + + self.acir_context.write_to_memory( + result_block_id, + ¤t_index, + &new_value, + )?; + + current_insert_index += 1; + if inner_elem_size_usize == current_insert_index { + current_insert_index = 0; + } } - Ok(vec![ - AcirValue::Var(new_slice_length, AcirType::field()), - AcirValue::Array(new_slice), - ]) + // let new_slice_val = AcirValue::Array(new_slice); + let element_type_sizes = if !can_omit_element_sizes_array(&slice_typ) { + Some(self.init_element_type_sizes_array( + &slice_typ, + slice_contents, + Some(slice), + dfg, + )?) + } else { + None + }; + let result = AcirValue::DynamicArray(AcirDynamicArray { + block_id: result_block_id, + len: slice_size, + element_type_sizes, + }); + + Ok(vec![AcirValue::Var(new_slice_length, AcirType::field()), result]) } Intrinsic::SliceRemove => { - // Slice insert with a constant index + // arguments = [slice_length, slice_contents, remove_index] let slice_length = self.convert_value(arguments[0], dfg).into_var()?; - let slice = self.convert_value(arguments[1], dfg); - let index = self.convert_value(arguments[2], dfg).into_var()?; + + let (slice_contents, slice_typ, block_id) = + self.check_array_is_initialized(arguments[1], dfg)?; + + let slice = self.convert_value(slice_contents, dfg); + let remove_index = self.convert_value(arguments[2], dfg).into_var()?; let one = self.acir_context.add_constant(FieldElement::one()); let new_slice_length = self.acir_context.sub_var(slice_length, one)?; - // TODO(#2462): allow slice remove with a constant index - // Slice remove is a little less obvious on how to implement due to the case - // of having a dynamic index - // The slice remove logic will need a more involved codegen - let index = self.acir_context.var_to_expression(index)?.to_const(); - let index = index - .expect("ICE: slice length should be fully tracked and constant by ACIR gen"); - let index = index.to_u128() as usize; + let slice_size = Self::flattened_value_size(&slice); let mut new_slice = Vector::new(); self.slice_intrinsic_input(&mut new_slice, slice)?; - // We do not return an index out of bounds error directly here - // as the length of the slice is dynamic, and length of `new_slice` - // represents the capacity of the slice, not the actual length. - // - // Constraints should be generated during SSA gen to tell the user - // they are attempting to remove at too large of an index. - // This check prevents a panic inside of the im::Vector remove method. - let removed_elem = if index < new_slice.len() { - // TODO(#3364): make sure that we have handled nested struct inputs - new_slice.remove(index) + // Compiler sanity check + assert_eq!( + new_slice.len(), + slice_size, + "ICE: The read flattened slice should match the computed size" + ); + + // Fetch the flattened index from the user provided index argument. + let element_size = slice_typ.element_size(); + let element_size_var = self.acir_context.add_constant(element_size); + let flat_remove_index = + self.acir_context.mul_var(remove_index, element_size_var)?; + let flat_user_index = + self.get_flattened_index(&slice_typ, slice_contents, flat_remove_index, dfg)?; + + // Fetch the values we are remove from the slice. + // In the case of non-nested slice the logic is simple as we do not + // need to account for the internal slice sizes or flattening the index. + // As we fetch the values we can determine the size of the removed values + // which we will later use for writing the correct resulting slice. + let mut popped_elements = Vec::new(); + let mut popped_elements_size = 0; + // Set a temp index just for fetching from the original slice as `array_get_value` mutates + // the index internally. + let mut temp_index = flat_user_index; + if !slice_typ.is_nested_slice() { + for res in &result_ids[2..(2 + element_size)] { + let element = self.array_get_value( + &dfg.type_of_value(*res), + block_id, + &mut temp_index, + &[], + )?; + let elem_size = Self::flattened_value_size(&element); + popped_elements_size += elem_size; + popped_elements.push(element); + } } else { - // This is a dummy value which should never be used if the appropriate - // slice access checks are generated before this slice remove call. - AcirValue::Var(slice_length, AcirType::field()) + let slice_sizes = self.slice_sizes.get(&slice_contents); + let mut slice_sizes = + slice_sizes.expect("ICE: should have slice sizes").clone(); + // We want to remove the parent size as we are fetching the child + slice_sizes.remove(0); + + for res in &result_ids[2..(2 + element_size)] { + let element = self.array_get_value( + &dfg.type_of_value(*res), + block_id, + &mut temp_index, + &slice_sizes, + )?; + let elem_size = Self::flattened_value_size(&element); + popped_elements_size += elem_size; + popped_elements.push(element); + } + } + + // Go through the entire slice argument and determine what value should be written to the new slice. + // 1. If the current index is greater than the removal index we must write the next value + // from the original slice to the current index + // 2. At the end of the slice reading from the next value of the original slice + // can lead to a potential out of bounds error. In this case we just fetch from the original slice + // at the current index. As we are decreasing the slice in length, this is a safe operation. + let result_block_id = self.block_id(&result_ids[1]); + self.initialize_array( + result_block_id, + slice_size, + Some(AcirValue::Array(new_slice.clone())), + )?; + for i in 0..slice_size { + let current_index = self.acir_context.add_constant(i); + + let value_current_index = &new_slice[i].borrow_var()?; + + if slice_size > (i + popped_elements_size) { + let shifted_index = + self.acir_context.add_constant(i + popped_elements_size); + + let value_shifted_index = + self.acir_context.read_from_memory(block_id, &shifted_index)?; + + let use_shifted_value = self.acir_context.more_than_eq_var( + current_index, + flat_user_index, + 64, + self.current_side_effects_enabled_var, + )?; + + let shifted_value_pred = + self.acir_context.mul_var(value_shifted_index, use_shifted_value)?; + let not_pred = self.acir_context.sub_var(one, use_shifted_value)?; + let current_value_pred = + self.acir_context.mul_var(not_pred, *value_current_index)?; + + let new_value = + self.acir_context.add_var(shifted_value_pred, current_value_pred)?; + + self.acir_context.write_to_memory( + result_block_id, + ¤t_index, + &new_value, + )?; + }; + } + + let new_slice_val = AcirValue::Array(new_slice); + let element_type_sizes = if !can_omit_element_sizes_array(&slice_typ) { + Some(self.init_element_type_sizes_array( + &slice_typ, + slice_contents, + Some(new_slice_val), + dfg, + )?) + } else { + None }; + let result = AcirValue::DynamicArray(AcirDynamicArray { + block_id: result_block_id, + len: slice_size, + element_type_sizes, + }); - Ok(vec![ - AcirValue::Var(new_slice_length, AcirType::field()), - AcirValue::Array(new_slice), - removed_elem, - ]) + let mut result = vec![AcirValue::Var(new_slice_length, AcirType::field()), result]; + result.append(&mut popped_elements); + + Ok(result) } _ => todo!("expected a black box function"), } @@ -1959,7 +2385,7 @@ impl Context { AcirValue::DynamicArray(AcirDynamicArray { block_id, len, .. }) => { for i in 0..len { // We generate witnesses corresponding to the array values - let index_var = self.acir_context.add_constant(FieldElement::from(i as u128)); + let index_var = self.acir_context.add_constant(i); let value_read_var = self.acir_context.read_from_memory(block_id, &index_var)?; @@ -2041,3 +2467,16 @@ impl Context { } } } + +// We can omit the element size array for arrays which have elements of size 1 and do not contain slices. +// TODO: remove restriction on size 1 elements. +fn can_omit_element_sizes_array(array_typ: &Type) -> bool { + if array_typ.contains_slice_element() { + return false; + } + let Type::Array(types, _) = array_typ else { + panic!("ICE: expected array type"); + }; + + types.len() == 1 && types[0].flattened_size() == 1 +} diff --git a/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs b/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs new file mode 100644 index 0000000000..7f33708932 --- /dev/null +++ b/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs @@ -0,0 +1,144 @@ +use std::rc::Rc; + +use crate::ssa::ir::{types::Type, value::ValueId}; +use acvm::FieldElement; +use fxhash::FxHashMap as HashMap; +use noirc_frontend::hir_def::function::FunctionSignature; + +use super::FunctionBuilder; + +/// Used to create a data bus, which is an array of private inputs +/// replacing public inputs +pub(crate) struct DataBusBuilder { + pub(crate) values: im::Vector, + index: usize, + pub(crate) map: HashMap, + pub(crate) databus: Option, +} + +impl DataBusBuilder { + pub(crate) fn new() -> DataBusBuilder { + DataBusBuilder { + index: 0, + map: HashMap::default(), + databus: None, + values: im::Vector::new(), + } + } + + /// Generates a boolean vector telling which (ssa) parameter from the given function signature + /// are tagged with databus visibility + pub(crate) fn is_databus(main_signature: &FunctionSignature) -> Vec { + let mut params_is_databus = Vec::new(); + + for param in &main_signature.0 { + let is_databus = match param.2 { + noirc_frontend::Visibility::Public | noirc_frontend::Visibility::Private => false, + noirc_frontend::Visibility::DataBus => true, + }; + let len = param.1.field_count() as usize; + params_is_databus.extend(vec![is_databus; len]); + } + params_is_databus + } +} + +#[derive(Clone, Default, Debug)] +pub(crate) struct DataBus { + pub(crate) call_data: Option, + pub(crate) call_data_map: HashMap, + pub(crate) return_data: Option, +} + +impl DataBus { + /// Updates the databus values with the provided function + pub(crate) fn map_values(&self, mut f: impl FnMut(ValueId) -> ValueId) -> DataBus { + let mut call_data_map = HashMap::default(); + for (k, v) in self.call_data_map.iter() { + call_data_map.insert(f(*k), *v); + } + DataBus { + call_data: self.call_data.map(&mut f), + call_data_map, + return_data: self.return_data.map(&mut f), + } + } + + /// Construct a databus from call_data and return_data data bus builders + pub(crate) fn get_data_bus(call_data: DataBusBuilder, return_data: DataBusBuilder) -> DataBus { + DataBus { + call_data: call_data.databus, + call_data_map: call_data.map, + return_data: return_data.databus, + } + } +} + +impl FunctionBuilder { + /// Insert a value into a data bus builder + fn add_to_data_bus(&mut self, value: ValueId, databus: &mut DataBusBuilder) { + assert!(databus.databus.is_none(), "initialising finalized call data"); + let typ = self.current_function.dfg[value].get_type().clone(); + match typ { + Type::Numeric(_) => { + databus.values.push_back(value); + databus.index += 1; + } + Type::Reference(_) => unreachable!(), + Type::Array(typ, len) => { + assert!(typ.len() == 1, "unsupported composite type"); + databus.map.insert(value, databus.index); + for i in 0..len { + // load each element of the array + let index = self + .current_function + .dfg + .make_constant(FieldElement::from(i as i128), Type::field()); + let element = self.insert_array_get(value, index, typ[0].clone()); + self.add_to_data_bus(element, databus); + } + } + Type::Slice(_) => unreachable!(), + Type::Function => unreachable!(), + } + } + + /// Create a data bus builder from a list of values + pub(crate) fn initialize_data_bus( + &mut self, + values: &[ValueId], + mut databus: DataBusBuilder, + ) -> DataBusBuilder { + for value in values { + self.add_to_data_bus(*value, &mut databus); + } + let len = databus.values.len(); + + let array = if len > 0 { + let array = + self.array_constant(databus.values, Type::Array(Rc::new(vec![Type::field()]), len)); + Some(array) + } else { + None + }; + + DataBusBuilder { index: 0, map: databus.map, databus: array, values: im::Vector::new() } + } + + /// Generate the data bus for call-data, based on the parameters of the entry block + /// and a boolean vector telling which ones are call-data + pub(crate) fn call_data_bus(&mut self, is_params_databus: Vec) -> DataBusBuilder { + //filter parameters of the first block that have call-data visilibity + let first_block = self.current_function.entry_block(); + let params = self.current_function.dfg[first_block].parameters(); + let mut databus_param = Vec::new(); + for (param, is_databus) in params.iter().zip(is_params_databus) { + if is_databus { + databus_param.push(param.to_owned()); + } + } + // create the call-data-bus from the filtered list + let call_data = DataBusBuilder::new(); + self.initialize_data_bus(&databus_param, call_data) + } +} diff --git a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index 058f91adac..56a22fd410 100644 --- a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -1,3 +1,5 @@ +pub(crate) mod data_bus; + use std::{borrow::Cow, rc::Rc}; use acvm::FieldElement; @@ -170,8 +172,9 @@ impl FunctionBuilder { /// Insert an allocate instruction at the end of the current block, allocating the /// given amount of field elements. Returns the result of the allocate instruction, /// which is always a Reference to the allocated data. - pub(crate) fn insert_allocate(&mut self) -> ValueId { - self.insert_instruction(Instruction::Allocate, None).first() + pub(crate) fn insert_allocate(&mut self, element_type: Type) -> ValueId { + let reference_type = Type::Reference(Rc::new(element_type)); + self.insert_instruction(Instruction::Allocate, Some(vec![reference_type])).first() } pub(crate) fn set_location(&mut self, location: Location) -> &mut FunctionBuilder { @@ -260,22 +263,6 @@ impl FunctionBuilder { arguments: Vec, result_types: Vec, ) -> Cow<[ValueId]> { - if let Value::Intrinsic(intrinsic) = &self.current_function.dfg[func] { - if intrinsic == &Intrinsic::WrappingShiftLeft { - let result_type = self.current_function.dfg.type_of_value(arguments[0]); - let bit_size = match result_type { - Type::Numeric(NumericType::Signed { bit_size }) - | Type::Numeric(NumericType::Unsigned { bit_size }) => bit_size, - _ => { - unreachable!("ICE: Truncation attempted on non-integer"); - } - }; - return self - .insert_wrapping_shift_left(arguments[0], arguments[1], bit_size) - .results(); - } - } - self.insert_instruction(Instruction::Call { func, arguments }, Some(result_types)).results() } @@ -290,50 +277,48 @@ impl FunctionBuilder { /// Insert ssa instructions which computes lhs << rhs by doing lhs*2^rhs /// and truncate the result to bit_size - fn insert_wrapping_shift_left( + pub(crate) fn insert_wrapping_shift_left( &mut self, lhs: ValueId, rhs: ValueId, bit_size: u32, - ) -> InsertInstructionResult { + ) -> ValueId { let base = self.field_constant(FieldElement::from(2_u128)); let typ = self.current_function.dfg.type_of_value(lhs); - let (max_bit, pow) = if let Some(rhs_constant) = - self.current_function.dfg.get_numeric_constant(rhs) - { - // Happy case is that we know precisely by how many bits the the integer will - // increase: lhs_bit_size + rhs - let (rhs_bit_size_pow_2, overflows) = - 2_u32.overflowing_pow(rhs_constant.to_u128() as u32); - if overflows { - let zero = self.numeric_constant(FieldElement::zero(), typ); - return InsertInstructionResult::SimplifiedTo(zero); - } - let pow = self.numeric_constant(FieldElement::from(rhs_bit_size_pow_2 as u128), typ); - (bit_size + (rhs_constant.to_u128() as u32), pow) - } else { - // we use a predicate to nullify the result in case of overflow - let bit_size_var = - self.numeric_constant(FieldElement::from(bit_size as u128), typ.clone()); - let overflow = self.insert_binary(rhs, BinaryOp::Lt, bit_size_var); - let one = self.numeric_constant(FieldElement::one(), Type::unsigned(1)); - let predicate = self.insert_binary(overflow, BinaryOp::Eq, one); - let predicate = self.insert_cast(predicate, typ.clone()); - - let pow = self.pow(base, rhs); - let pow = self.insert_cast(pow, typ); - (FieldElement::max_num_bits(), self.insert_binary(predicate, BinaryOp::Mul, pow)) - }; + let (max_bit, pow) = + if let Some(rhs_constant) = self.current_function.dfg.get_numeric_constant(rhs) { + // Happy case is that we know precisely by how many bits the the integer will + // increase: lhs_bit_size + rhs + let (rhs_bit_size_pow_2, overflows) = + 2_u128.overflowing_pow(rhs_constant.to_u128() as u32); + if overflows { + assert!(bit_size < 128, "ICE - shift left with big integers are not supported"); + if bit_size < 128 { + let zero = self.numeric_constant(FieldElement::zero(), typ); + return InsertInstructionResult::SimplifiedTo(zero).first(); + } + } + let pow = self.numeric_constant(FieldElement::from(rhs_bit_size_pow_2), typ); + (bit_size + (rhs_constant.to_u128() as u32), pow) + } else { + // we use a predicate to nullify the result in case of overflow + let bit_size_var = + self.numeric_constant(FieldElement::from(bit_size as u128), typ.clone()); + let overflow = self.insert_binary(rhs, BinaryOp::Lt, bit_size_var); + let one = self.numeric_constant(FieldElement::one(), Type::unsigned(1)); + let predicate = self.insert_binary(overflow, BinaryOp::Eq, one); + let predicate = self.insert_cast(predicate, typ.clone()); + + let pow = self.pow(base, rhs); + let pow = self.insert_cast(pow, typ); + (FieldElement::max_num_bits(), self.insert_binary(predicate, BinaryOp::Mul, pow)) + }; - let instruction = Instruction::Binary(Binary { lhs, rhs: pow, operator: BinaryOp::Mul }); if max_bit <= bit_size { - self.insert_instruction(instruction, None) + self.insert_binary(lhs, BinaryOp::Mul, pow) } else { - let result = self.insert_instruction(instruction, None).first(); - self.insert_instruction( - Instruction::Truncate { value: result, bit_size, max_bit_size: max_bit }, - None, - ) + let result = self.insert_binary(lhs, BinaryOp::Mul, pow); + self.insert_truncate(result, bit_size, max_bit) } } @@ -471,6 +456,27 @@ impl FunctionBuilder { _ => None, } } + + /// Insert instructions to increment the reference count of any array(s) stored + /// within the given value. If the given value is not an array and does not contain + /// any arrays, this does nothing. + pub(crate) fn increment_array_reference_count(&mut self, value: ValueId) { + match self.type_of_value(value) { + Type::Numeric(_) => (), + Type::Function => (), + Type::Reference(element) => { + if element.contains_an_array() { + let value = self.insert_load(value, element.as_ref().clone()); + self.increment_array_reference_count(value); + } + } + Type::Array(..) | Type::Slice(..) => { + self.insert_instruction(Instruction::IncrementRc { value }, None); + // If there are nested arrays or slices, we wait until ArrayGet + // is issued to increment the count of that array. + } + } + } } impl std::ops::Index for FunctionBuilder { diff --git a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs index 3cb6736007..abddbfb74c 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/dfg.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/dfg.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use crate::ssa::ir::instruction::SimplifyResult; +use crate::ssa::{function_builder::data_bus::DataBus, ir::instruction::SimplifyResult}; use super::{ basic_block::{BasicBlock, BasicBlockId}, @@ -80,6 +80,8 @@ pub(crate) struct DataFlowGraph { /// Instructions inserted by internal SSA passes that don't correspond to user code /// may not have a corresponding location. locations: HashMap, + + pub(crate) data_bus: DataBus, } pub(crate) type CallStack = im::Vector; @@ -318,7 +320,7 @@ impl DataFlowGraph { /// True if the type of this value is Type::Reference. /// Using this method over type_of_value avoids cloning the value's type. pub(crate) fn value_is_reference(&self, value: ValueId) -> bool { - matches!(self.values[value].get_type(), Type::Reference) + matches!(self.values[value].get_type(), Type::Reference(_)) } /// Appends a result type to the instruction. @@ -521,13 +523,13 @@ impl<'dfg> InsertInstructionResult<'dfg> { #[cfg(test)] mod tests { use super::DataFlowGraph; - use crate::ssa::ir::instruction::Instruction; + use crate::ssa::ir::{instruction::Instruction, types::Type}; #[test] fn make_instruction() { let mut dfg = DataFlowGraph::default(); let ins = Instruction::Allocate; - let ins_id = dfg.make_instruction(ins, None); + let ins_id = dfg.make_instruction(ins, Some(vec![Type::field()])); let results = dfg.instruction_results(ins_id); assert_eq!(results.len(), 1); diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index 71e773e3f7..628ad638e6 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -46,7 +46,6 @@ pub(crate) enum Intrinsic { BlackBox(BlackBoxFunc), FromField, AsField, - WrappingShiftLeft, } impl std::fmt::Display for Intrinsic { @@ -69,7 +68,6 @@ impl std::fmt::Display for Intrinsic { Intrinsic::BlackBox(function) => write!(f, "{function}"), Intrinsic::FromField => write!(f, "from_field"), Intrinsic::AsField => write!(f, "as_field"), - Intrinsic::WrappingShiftLeft => write!(f, "wrapping_shift_left"), } } } @@ -94,8 +92,7 @@ impl Intrinsic { | Intrinsic::ToBits(_) | Intrinsic::ToRadix(_) | Intrinsic::FromField - | Intrinsic::AsField - | Intrinsic::WrappingShiftLeft => false, + | Intrinsic::AsField => false, // Some black box functions have side-effects Intrinsic::BlackBox(func) => matches!(func, BlackBoxFunc::RecursiveAggregation), @@ -122,7 +119,6 @@ impl Intrinsic { "to_be_bits" => Some(Intrinsic::ToBits(Endian::Big)), "from_field" => Some(Intrinsic::FromField), "as_field" => Some(Intrinsic::AsField), - "wrapping_shift_left" => Some(Intrinsic::WrappingShiftLeft), other => BlackBoxFunc::lookup(other).map(Intrinsic::BlackBox), } } @@ -186,6 +182,13 @@ pub(crate) enum Instruction { /// Creates a new array with the new value at the given index. All other elements are identical /// to those in the given array. This will not modify the original array. ArraySet { array: ValueId, index: ValueId, value: ValueId }, + + /// An instruction to increment the reference count of a value. + /// + /// This currently only has an effect in Brillig code where array sharing and copy on write is + /// implemented via reference counting. In ACIR code this is done with im::Vector and these + /// IncrementRc instructions are ignored. + IncrementRc { value: ValueId }, } impl Instruction { @@ -199,18 +202,19 @@ impl Instruction { match self { Instruction::Binary(binary) => binary.result_type(), Instruction::Cast(_, typ) => InstructionResultType::Known(typ.clone()), - Instruction::Allocate { .. } => InstructionResultType::Known(Type::Reference), Instruction::Not(value) | Instruction::Truncate { value, .. } => { InstructionResultType::Operand(*value) } Instruction::ArraySet { array, .. } => InstructionResultType::Operand(*array), Instruction::Constrain(..) | Instruction::Store { .. } - | Instruction::EnableSideEffects { .. } - | Instruction::RangeCheck { .. } => InstructionResultType::None, - Instruction::Load { .. } | Instruction::ArrayGet { .. } | Instruction::Call { .. } => { - InstructionResultType::Unknown - } + | Instruction::IncrementRc { .. } + | Instruction::RangeCheck { .. } + | Instruction::EnableSideEffects { .. } => InstructionResultType::None, + Instruction::Allocate { .. } + | Instruction::Load { .. } + | Instruction::ArrayGet { .. } + | Instruction::Call { .. } => InstructionResultType::Unknown, } } @@ -228,7 +232,11 @@ impl Instruction { use Instruction::*; match self { - Binary(_) | Cast(_, _) | Not(_) | ArrayGet { .. } | ArraySet { .. } => true, + Binary(bin) => { + // In ACIR, a division with a false predicate outputs (0,0), so it cannot replace another instruction unless they have the same predicate + bin.operator != BinaryOp::Div + } + Cast(_, _) | Not(_) | ArrayGet { .. } | ArraySet { .. } => true, // Unclear why this instruction causes problems. Truncate { .. } => false, @@ -239,6 +247,7 @@ impl Instruction { | Allocate | Load { .. } | Store { .. } + | IncrementRc { .. } | RangeCheck { .. } => false, Call { func, .. } => match dfg[*func] { @@ -270,7 +279,11 @@ impl Instruction { | ArrayGet { .. } | ArraySet { .. } => false, - Constrain(..) | Store { .. } | EnableSideEffects { .. } | RangeCheck { .. } => true, + Constrain(..) + | Store { .. } + | EnableSideEffects { .. } + | IncrementRc { .. } + | RangeCheck { .. } => true, // Some `Intrinsic`s have side effects so we must check what kind of `Call` this is. Call { func, .. } => match dfg[*func] { @@ -327,6 +340,7 @@ impl Instruction { Instruction::ArraySet { array, index, value } => { Instruction::ArraySet { array: f(*array), index: f(*index), value: f(*value) } } + Instruction::IncrementRc { value } => Instruction::IncrementRc { value: f(*value) }, Instruction::RangeCheck { value, max_bit_size, assert_message } => { Instruction::RangeCheck { value: f(*value), @@ -378,7 +392,7 @@ impl Instruction { Instruction::EnableSideEffects { condition } => { f(*condition); } - Instruction::RangeCheck { value, .. } => { + Instruction::IncrementRc { value } | Instruction::RangeCheck { value, .. } => { f(*value); } } @@ -419,12 +433,74 @@ impl Instruction { _ => None, } } - Instruction::Constrain(lhs, rhs, ..) => { + Instruction::Constrain(lhs, rhs, msg) => { if dfg.resolve(*lhs) == dfg.resolve(*rhs) { // Remove trivial case `assert_eq(x, x)` SimplifyResult::Remove } else { - SimplifyResult::None + match (&dfg[dfg.resolve(*lhs)], &dfg[dfg.resolve(*rhs)]) { + ( + Value::NumericConstant { constant, typ }, + Value::Instruction { instruction, .. }, + ) + | ( + Value::Instruction { instruction, .. }, + Value::NumericConstant { constant, typ }, + ) if *typ == Type::bool() => { + match dfg[*instruction] { + Instruction::Binary(Binary { + lhs, + rhs, + operator: BinaryOp::Eq, + }) if constant.is_one() => { + // Replace an explicit two step equality assertion + // + // v2 = eq v0, u32 v1 + // constrain v2 == u1 1 + // + // with a direct assertion of equality between the two values + // + // v2 = eq v0, u32 v1 + // constrain v0 == v1 + // + // Note that this doesn't remove the value `v2` as it may be used in other instructions, but it + // will likely be removed through dead instruction elimination. + + SimplifiedToInstruction(Instruction::Constrain( + lhs, + rhs, + msg.clone(), + )) + } + Instruction::Not(value) => { + // Replace an assertion that a not instruction is truthy + // + // v1 = not v0 + // constrain v1 == u1 1 + // + // with an assertion that the not instruction input is falsy + // + // v1 = not v0 + // constrain v0 == u1 0 + // + // Note that this doesn't remove the value `v1` as it may be used in other instructions, but it + // will likely be removed through dead instruction elimination. + let reversed_constant = FieldElement::from(!constant.is_one()); + let reversed_constant = + dfg.make_constant(reversed_constant, Type::bool()); + SimplifiedToInstruction(Instruction::Constrain( + value, + reversed_constant, + msg.clone(), + )) + } + + _ => None, + } + } + + _ => None, + } } } Instruction::ArrayGet { array, index } => { @@ -453,11 +529,23 @@ impl Instruction { } None } - Instruction::Truncate { value, bit_size, .. } => { + Instruction::Truncate { value, bit_size, max_bit_size } => { if let Some((numeric_constant, typ)) = dfg.get_numeric_constant_with_type(*value) { let integer_modulus = 2_u128.pow(*bit_size); let truncated = numeric_constant.to_u128() % integer_modulus; SimplifiedTo(dfg.make_constant(truncated.into(), typ)) + } else if let Value::Instruction { instruction, .. } = &dfg[dfg.resolve(*value)] { + if let Instruction::Truncate { bit_size: src_bit_size, .. } = &dfg[*instruction] + { + // If we're truncating the value to fit into the same or larger bit size then this is a noop. + if src_bit_size <= bit_size && src_bit_size <= max_bit_size { + SimplifiedTo(*value) + } else { + None + } + } else { + None + } } else { None } @@ -478,6 +566,7 @@ impl Instruction { Instruction::Allocate { .. } => None, Instruction::Load { .. } => None, Instruction::Store { .. } => None, + Instruction::IncrementRc { .. } => None, Instruction::RangeCheck { value, max_bit_size, .. } => { if let Some(numeric_constant) = dfg.get_numeric_constant(*value) { if numeric_constant.num_bits() < *max_bit_size { @@ -768,10 +857,19 @@ impl Binary { let zero = dfg.make_constant(FieldElement::zero(), Type::bool()); return SimplifyResult::SimplifiedTo(zero); } - if operand_type.is_unsigned() && rhs_is_zero { - // Unsigned values cannot be less than zero. - let zero = dfg.make_constant(FieldElement::zero(), Type::bool()); - return SimplifyResult::SimplifiedTo(zero); + if operand_type.is_unsigned() { + if rhs_is_zero { + // Unsigned values cannot be less than zero. + let zero = dfg.make_constant(FieldElement::zero(), Type::bool()); + return SimplifyResult::SimplifiedTo(zero); + } else if rhs_is_one { + let zero = dfg.make_constant(FieldElement::zero(), operand_type); + return SimplifyResult::SimplifiedToInstruction(Instruction::binary( + BinaryOp::Eq, + self.lhs, + zero, + )); + } } } BinaryOp::And => { diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs index f86a9245ca..956c7077b8 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs @@ -245,9 +245,6 @@ pub(super) fn simplify_call( let instruction = Instruction::Cast(arguments[0], ctrl_typevars.unwrap().remove(0)); SimplifyResult::SimplifiedToInstruction(instruction) } - Intrinsic::WrappingShiftLeft => { - unreachable!("ICE - wrapping shift left should have been proccessed before") - } } } diff --git a/compiler/noirc_evaluator/src/ssa/ir/printer.rs b/compiler/noirc_evaluator/src/ssa/ir/printer.rs index c6b1f3c752..2899b987c1 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/printer.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/printer.rs @@ -172,6 +172,9 @@ pub(crate) fn display_instruction( show(*value) ) } + Instruction::IncrementRc { value } => { + writeln!(f, "inc_rc {}", show(*value)) + } Instruction::RangeCheck { value, max_bit_size, .. } => { writeln!(f, "range_check {} to {} bits", show(*value), *max_bit_size,) } diff --git a/compiler/noirc_evaluator/src/ssa/ir/types.rs b/compiler/noirc_evaluator/src/ssa/ir/types.rs index 7fe0713e74..bae06a805d 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/types.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/types.rs @@ -25,7 +25,7 @@ pub(crate) enum Type { Numeric(NumericType), /// A reference to some value, such as an array - Reference, + Reference(Rc), /// An immutable array value with the given element type and length Array(Rc, usize), @@ -86,24 +86,39 @@ impl Type { } Type::Slice(_) => true, Type::Numeric(_) => false, - Type::Reference => false, + Type::Reference(_) => false, Type::Function => false, } } /// Returns the flattened size of a Type pub(crate) fn flattened_size(&self) -> usize { - let mut size = 0; match self { Type::Array(elements, len) => { - size = elements.iter().fold(size, |sum, elem| sum + (elem.flattened_size() * len)); + elements.iter().fold(0, |sum, elem| sum + (elem.flattened_size() * len)) } Type::Slice(_) => { unimplemented!("ICE: cannot fetch flattened slice size"); } - _ => size += 1, + _ => 1, + } + } + + pub(crate) fn is_nested_slice(&self) -> bool { + if let Type::Slice(element_types) = self { + element_types.as_ref().iter().any(|typ| typ.contains_slice_element()) + } else { + false + } + } + + /// True if this type is an array (or slice) or internally contains an array (or slice) + pub(crate) fn contains_an_array(&self) -> bool { + match self { + Type::Numeric(_) | Type::Function => false, + Type::Array(_, _) | Type::Slice(_) => true, + Type::Reference(element) => element.contains_an_array(), } - size } } @@ -112,13 +127,7 @@ impl NumericType { /// for the current NumericType. pub(crate) fn value_is_within_limits(self, field: FieldElement) -> bool { match self { - NumericType::Signed { bit_size } => { - let min = -(2i128.pow(bit_size - 1)); - let max = 2u128.pow(bit_size - 1) - 1; - // Signed integers are odd since they will overflow the field value - field <= max.into() || field >= min.into() - } - NumericType::Unsigned { bit_size } => { + NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size } => { let max = 2u128.pow(bit_size) - 1; field <= max.into() } @@ -136,7 +145,7 @@ impl std::fmt::Display for Type { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Type::Numeric(numeric) => numeric.fmt(f), - Type::Reference => write!(f, "reference"), + Type::Reference(element) => write!(f, "&mut {element}"), Type::Array(element, length) => { let elements = vecmap(element.iter(), |element| element.to_string()); write!(f, "[{}; {length}]", elements.join(", ")) diff --git a/compiler/noirc_evaluator/src/ssa/opt/die.rs b/compiler/noirc_evaluator/src/ssa/opt/die.rs index 3db95f6ad9..492e96dc08 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/die.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/die.rs @@ -7,7 +7,7 @@ use crate::ssa::{ basic_block::{BasicBlock, BasicBlockId}, dfg::DataFlowGraph, function::Function, - instruction::InstructionId, + instruction::{Instruction, InstructionId}, post_order::PostOrder, value::{Value, ValueId}, }, @@ -33,11 +33,17 @@ impl Ssa { /// of its instructions are needed elsewhere. fn dead_instruction_elimination(function: &mut Function) { let mut context = Context::default(); + if let Some(call_data) = function.dfg.data_bus.call_data { + context.mark_used_instruction_results(&function.dfg, call_data); + } + let blocks = PostOrder::with_function(function); for block in blocks.as_slice() { context.remove_unused_instructions_in_block(function, *block); } + + context.remove_increment_rc_instructions(&mut function.dfg); } /// Per function context for tracking unused values and which instructions to remove. @@ -45,6 +51,11 @@ fn dead_instruction_elimination(function: &mut Function) { struct Context { used_values: HashSet, instructions_to_remove: HashSet, + + /// IncrementRc instructions must be revisited after the main DIE pass since + /// they are technically side-effectful but we stil want to remove them if their + /// `value` parameter is not used elsewhere. + increment_rc_instructions: Vec<(InstructionId, BasicBlockId)>, } impl Context { @@ -67,14 +78,19 @@ impl Context { let block = &function.dfg[block_id]; self.mark_terminator_values_as_used(function, block); - for instruction in block.instructions().iter().rev() { - if self.is_unused(*instruction, function) { - self.instructions_to_remove.insert(*instruction); + for instruction_id in block.instructions().iter().rev() { + if self.is_unused(*instruction_id, function) { + self.instructions_to_remove.insert(*instruction_id); } else { - let instruction = &function.dfg[*instruction]; - instruction.for_each_value(|value| { - self.mark_used_instruction_results(&function.dfg, value); - }); + let instruction = &function.dfg[*instruction_id]; + + if let Instruction::IncrementRc { .. } = instruction { + self.increment_rc_instructions.push((*instruction_id, block_id)); + } else { + instruction.for_each_value(|value| { + self.mark_used_instruction_results(&function.dfg, value); + }); + } } } @@ -119,11 +135,28 @@ impl Context { self.mark_used_instruction_results(dfg, *elem); } } + Value::Param { .. } => { + self.used_values.insert(value_id); + } _ => { // Does not comprise of any instruction results } } } + + fn remove_increment_rc_instructions(self, dfg: &mut DataFlowGraph) { + for (increment_rc, block) in self.increment_rc_instructions { + let value = match &dfg[increment_rc] { + Instruction::IncrementRc { value } => *value, + other => unreachable!("Expected IncrementRc instruction, found {other:?}"), + }; + + // This could be more efficient if we have to remove multiple IncrementRcs in a single block + if !self.used_values.contains(&value) { + dfg[block].instructions_mut().retain(|instruction| *instruction != increment_rc); + } + } + } } #[cfg(test)] @@ -176,10 +209,10 @@ mod test { builder.switch_to_block(b1); let _v3 = builder.add_block_parameter(b1, Type::field()); - let v4 = builder.insert_allocate(); + let v4 = builder.insert_allocate(Type::field()); let _v5 = builder.insert_load(v4, Type::field()); - let v6 = builder.insert_allocate(); + let v6 = builder.insert_allocate(Type::field()); builder.insert_store(v6, one); let v7 = builder.insert_load(v6, Type::field()); let v8 = builder.insert_binary(v7, BinaryOp::Add, one); diff --git a/compiler/noirc_evaluator/src/ssa/opt/fill_internal_slices.rs b/compiler/noirc_evaluator/src/ssa/opt/fill_internal_slices.rs index d12b01b919..f5e9598114 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/fill_internal_slices.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/fill_internal_slices.rs @@ -46,7 +46,7 @@ use crate::ssa::{ ir::{ basic_block::BasicBlockId, dfg::CallStack, - function::Function, + function::{Function, RuntimeType}, function_inserter::FunctionInserter, instruction::{Instruction, InstructionId, Intrinsic}, post_order::PostOrder, @@ -62,8 +62,17 @@ use fxhash::FxHashMap as HashMap; impl Ssa { pub(crate) fn fill_internal_slices(mut self) -> Ssa { for function in self.functions.values_mut() { - let mut context = Context::new(function); - context.process_blocks(); + // This pass is only necessary for generating ACIR and thus we should not + // process Brillig functions. + // The pass is also currently only setup to handle a function with a single flattened block. + // For complex Brillig functions we can expect this pass to panic. + if function.runtime() == RuntimeType::Acir { + let databus = function.dfg.data_bus.clone(); + let mut context = Context::new(function); + context.process_blocks(); + // update the databus with the new array instructions + function.dfg.data_bus = databus.map_values(|t| context.inserter.resolve(t)); + } } self } @@ -168,6 +177,9 @@ impl<'f> Context<'f> { panic!("ICE: should have inner slice set for {slice_value}") }); slice_sizes.insert(results[0], inner_slice.clone()); + if slice_value != results[0] { + self.mapped_slice_values.insert(slice_value, results[0]); + } } } } @@ -192,17 +204,11 @@ impl<'f> Context<'f> { let inner_sizes = slice_sizes.get_mut(array).expect("ICE expected slice sizes"); inner_sizes.1.push(*value); - - let value_parent = self.resolve_slice_parent(*value); - if slice_values.contains(&value_parent) { - // Map the value parent to the current array in case nested slices - // from the current array are set to larger values later in the program - self.mapped_slice_values.insert(value_parent, *array); - } } if let Some(inner_sizes) = slice_sizes.get_mut(array) { let inner_sizes = inner_sizes.clone(); + slice_sizes.insert(results[0], inner_sizes); self.mapped_slice_values.insert(*array, results[0]); @@ -218,14 +224,27 @@ impl<'f> Context<'f> { | Intrinsic::SlicePopBack | Intrinsic::SliceInsert | Intrinsic::SliceRemove => (1, 1), - Intrinsic::SlicePopFront => (1, 2), + // `pop_front` returns the popped element, and then the respective slice. + // This means in the case of a slice with structs, the result index of the popped slice + // will change depending on the number of elements in the struct. + // For example, a slice with four elements will look as such in SSA: + // v3, v4, v5, v6, v7, v8 = call slice_pop_front(v1, v2) + // where v7 is the slice length and v8 is the popped slice itself. + Intrinsic::SlicePopFront => (1, results.len() - 1), _ => return, }; + let slice_contents = arguments[argument_index]; match intrinsic { Intrinsic::SlicePushBack | Intrinsic::SlicePushFront | Intrinsic::SliceInsert => { - let slice_contents = arguments[argument_index]; + for arg in &arguments[(argument_index + 1)..] { + let element_typ = self.inserter.function.dfg.type_of_value(*arg); + if element_typ.contains_slice_element() { + slice_values.push(*arg); + self.compute_slice_sizes(*arg, slice_sizes); + } + } if let Some(inner_sizes) = slice_sizes.get_mut(&slice_contents) { inner_sizes.0 += 1; @@ -234,12 +253,12 @@ impl<'f> Context<'f> { self.mapped_slice_values .insert(slice_contents, results[result_index]); + self.slice_parents.insert(results[result_index], slice_contents); } } Intrinsic::SlicePopBack - | Intrinsic::SlicePopFront - | Intrinsic::SliceRemove => { - let slice_contents = arguments[argument_index]; + | Intrinsic::SliceRemove + | Intrinsic::SlicePopFront => { // We do not decrement the size on intrinsics that could remove values from a slice. // This is because we could potentially go back to the smaller slice and not fill in dummies. // This pass should be tracking the potential max that a slice ***could be*** @@ -249,6 +268,7 @@ impl<'f> Context<'f> { self.mapped_slice_values .insert(slice_contents, results[result_index]); + self.slice_parents.insert(results[result_index], slice_contents); } } _ => {} @@ -271,7 +291,6 @@ impl<'f> Context<'f> { if slice_values.contains(array) { let (new_array_op_instr, call_stack) = self.get_updated_array_op_instr(*array, slice_sizes, instruction); - self.inserter.push_instruction_value( new_array_op_instr, instruction, @@ -282,6 +301,55 @@ impl<'f> Context<'f> { self.inserter.push_instruction(instruction, block); } } + Instruction::Call { func: _, arguments } => { + let mut args_to_replace = Vec::new(); + for (i, arg) in arguments.iter().enumerate() { + let element_typ = self.inserter.function.dfg.type_of_value(*arg); + if slice_values.contains(arg) && element_typ.contains_slice_element() { + args_to_replace.push((i, *arg)); + } + } + if args_to_replace.is_empty() { + self.inserter.push_instruction(instruction, block); + } else { + // Using the original slice is ok to do as during collection of slice information + // we guarantee that only the arguments to slice intrinsic calls can be replaced. + let slice_contents = arguments[1]; + + let element_typ = self.inserter.function.dfg.type_of_value(arguments[1]); + let elem_depth = Self::compute_nested_slice_depth(&element_typ); + + let mut max_sizes = Vec::new(); + max_sizes.resize(elem_depth, 0); + // We want the max for the parent of the argument + let parent = self.resolve_slice_parent(slice_contents); + self.compute_slice_max_sizes(parent, slice_sizes, &mut max_sizes, 0); + + for (index, arg) in args_to_replace { + let element_typ = self.inserter.function.dfg.type_of_value(arg); + max_sizes.remove(0); + let new_array = + self.attach_slice_dummies(&element_typ, Some(arg), false, &max_sizes); + + let instruction_id = instruction; + let (instruction, call_stack) = + self.inserter.map_instruction(instruction_id); + let new_call_instr = match instruction { + Instruction::Call { func, mut arguments } => { + arguments[index] = new_array; + Instruction::Call { func, arguments } + } + _ => panic!("Expected call instruction"), + }; + self.inserter.push_instruction_value( + new_call_instr, + instruction_id, + block, + call_stack, + ); + } + } + } _ => { self.inserter.push_instruction(instruction, block); } @@ -308,6 +376,7 @@ impl<'f> Context<'f> { let typ = self.inserter.function.dfg.type_of_value(array_id); let depth = Self::compute_nested_slice_depth(&typ); max_sizes.resize(depth, 0); + max_sizes[0] = *current_size; self.compute_slice_max_sizes(array_id, slice_sizes, &mut max_sizes, 1); @@ -364,9 +433,12 @@ impl<'f> Context<'f> { if let Some(value) = value { let mut slice = im::Vector::new(); - let array = match self.inserter.function.dfg[value].clone() { + let value = self.inserter.function.dfg[value].clone(); + let array = match value { Value::Array { array, .. } => array, - _ => panic!("Expected an array value"), + _ => { + panic!("Expected an array value"); + } }; if is_parent_slice { @@ -398,7 +470,7 @@ impl<'f> Context<'f> { self.inserter.function.dfg.make_array(slice, typ.clone()) } } - Type::Reference => { + Type::Reference(_) => { unreachable!("ICE: Generating dummy data for references is unsupported") } Type::Function => { @@ -481,7 +553,6 @@ impl<'f> Context<'f> { self.compute_slice_max_sizes(*inner_slice, slice_sizes, max_sizes, depth + 1); } - max_sizes[depth] = max; if max > max_sizes[depth] { max_sizes[depth] = max; } diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index d2ed21c60d..f0ad610948 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -640,22 +640,9 @@ impl<'f> Context<'f> { match instruction { Instruction::Constrain(lhs, rhs, message) => { // Replace constraint `lhs == rhs` with `condition * lhs == condition * rhs`. + let lhs = self.handle_constrain_arg_side_effects(lhs, condition, &call_stack); + let rhs = self.handle_constrain_arg_side_effects(rhs, condition, &call_stack); - // Condition needs to be cast to argument type in order to multiply them together. - let argument_type = self.inserter.function.dfg.type_of_value(lhs); - let casted_condition = self.insert_instruction( - Instruction::Cast(condition, argument_type), - call_stack.clone(), - ); - - let lhs = self.insert_instruction( - Instruction::binary(BinaryOp::Mul, lhs, casted_condition), - call_stack.clone(), - ); - let rhs = self.insert_instruction( - Instruction::binary(BinaryOp::Mul, rhs, casted_condition), - call_stack, - ); Instruction::Constrain(lhs, rhs, message) } Instruction::Store { address, value } => { @@ -685,6 +672,90 @@ impl<'f> Context<'f> { } } + /// Given the arguments of a constrain instruction, multiplying them by the branch's condition + /// requires special handling in the case of complex types. + fn handle_constrain_arg_side_effects( + &mut self, + argument: ValueId, + condition: ValueId, + call_stack: &CallStack, + ) -> ValueId { + let argument_type = self.inserter.function.dfg.type_of_value(argument); + + match &argument_type { + Type::Numeric(_) => { + // Condition needs to be cast to argument type in order to multiply them together. + let casted_condition = self.insert_instruction( + Instruction::Cast(condition, argument_type), + call_stack.clone(), + ); + + self.insert_instruction( + Instruction::binary(BinaryOp::Mul, argument, casted_condition), + call_stack.clone(), + ) + } + Type::Array(_, _) => { + self.handle_array_constrain_arg(argument_type, argument, condition, call_stack) + } + Type::Slice(_) => { + panic!("Cannot use slices directly in a constrain statement") + } + Type::Reference(_) => { + panic!("Cannot use references directly in a constrain statement") + } + Type::Function => { + panic!("Cannot use functions directly in a constrain statement") + } + } + } + + fn handle_array_constrain_arg( + &mut self, + typ: Type, + argument: ValueId, + condition: ValueId, + call_stack: &CallStack, + ) -> ValueId { + let mut new_array = im::Vector::new(); + + let (element_types, len) = match &typ { + Type::Array(elements, len) => (elements, *len), + _ => panic!("Expected array type"), + }; + + for i in 0..len { + for (element_index, element_type) in element_types.iter().enumerate() { + let index = ((i * element_types.len() + element_index) as u128).into(); + let index = self.inserter.function.dfg.make_constant(index, Type::field()); + + let typevars = Some(vec![element_type.clone()]); + + let mut get_element = |array, typevars| { + let get = Instruction::ArrayGet { array, index }; + self.inserter + .function + .dfg + .insert_instruction_and_results( + get, + self.inserter.function.entry_block(), + typevars, + CallStack::new(), + ) + .first() + }; + + let element = get_element(argument, typevars); + + new_array.push_back( + self.handle_constrain_arg_side_effects(element, condition, call_stack), + ); + } + } + + self.inserter.function.dfg.make_array(new_array, typ) + } + fn undo_stores_in_then_branch(&mut self, then_branch: &Branch) { for (address, store) in &then_branch.store_values { let address = *address; @@ -817,7 +888,7 @@ mod test { #[test] fn merge_stores() { // fn main f0 { - // b0(v0: u1, v1: ref): + // b0(v0: u1, v1: &mut Field): // jmpif v0, then: b1, else: b2 // b1(): // store v1, Field 5 @@ -832,7 +903,7 @@ mod test { let b2 = builder.insert_block(); let v0 = builder.add_parameter(Type::bool()); - let v1 = builder.add_parameter(Type::Reference); + let v1 = builder.add_parameter(Type::Reference(Rc::new(Type::field()))); builder.terminate_with_jmpif(v0, b1, b2); @@ -894,7 +965,7 @@ mod test { let b3 = builder.insert_block(); let v0 = builder.add_parameter(Type::bool()); - let v1 = builder.add_parameter(Type::Reference); + let v1 = builder.add_parameter(Type::Reference(Rc::new(Type::field()))); builder.terminate_with_jmpif(v0, b1, b2); @@ -935,7 +1006,6 @@ mod test { // } let ssa = ssa.flatten_cfg(); let main = ssa.main(); - println!("{ssa}"); assert_eq!(main.reachable_blocks().len(), 1); let store_count = count_instruction(main, |ins| matches!(ins, Instruction::Store { .. })); @@ -993,7 +1063,7 @@ mod test { let c1 = builder.add_parameter(Type::bool()); let c4 = builder.add_parameter(Type::bool()); - let r1 = builder.insert_allocate(); + let r1 = builder.insert_allocate(Type::field()); let store_value = |builder: &mut FunctionBuilder, value: u128| { let value = builder.field_constant(value); @@ -1144,7 +1214,7 @@ mod test { builder.terminate_with_jmpif(v0, b1, b2); builder.switch_to_block(b1); - let v2 = builder.insert_allocate(); + let v2 = builder.insert_allocate(Type::field()); let zero = builder.field_constant(0u128); builder.insert_store(v2, zero); let _v4 = builder.insert_load(v2, Type::field()); @@ -1313,7 +1383,7 @@ mod test { let v8 = builder.insert_binary(v6, BinaryOp::Mod, i_two); let v9 = builder.insert_cast(v8, Type::bool()); - let v10 = builder.insert_allocate(); + let v10 = builder.insert_allocate(Type::field()); builder.insert_store(v10, zero); builder.terminate_with_jmpif(v9, b1, b2); @@ -1412,9 +1482,9 @@ mod test { let ten = builder.field_constant(10u128); let one_hundred = builder.field_constant(100u128); - let v0 = builder.insert_allocate(); + let v0 = builder.insert_allocate(Type::field()); builder.insert_store(v0, zero); - let v2 = builder.insert_allocate(); + let v2 = builder.insert_allocate(Type::field()); builder.insert_store(v2, two); let v4 = builder.insert_load(v2, Type::field()); let v5 = builder.insert_binary(v4, BinaryOp::Lt, two); diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs index 32979f7863..446560f45f 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs @@ -60,7 +60,7 @@ impl<'a> ValueMerger<'a> { typ @ Type::Slice(_) => { self.merge_slice_values(typ, then_condition, else_condition, then_value, else_value) } - Type::Reference => panic!("Cannot return references from an if expression"), + Type::Reference(_) => panic!("Cannot return references from an if expression"), Type::Function => panic!("Cannot return functions from an if expression"), } } @@ -333,7 +333,7 @@ impl<'a> ValueMerger<'a> { // to accurately construct dummy data unreachable!("ICE: Cannot return a slice of slices from an if expression") } - Type::Reference => { + Type::Reference(_) => { unreachable!("ICE: Merging references is unsupported") } Type::Function => { diff --git a/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index ed2484feba..b4f12b2f89 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -139,11 +139,15 @@ impl InlineContext { context.blocks.insert(context.source_function.entry_block(), entry_block); context.inline_blocks(ssa); + // translate databus values + let databus = entry_point.dfg.data_bus.map_values(|t| context.translate_value(t)); // Finally, we should have 1 function left representing the inlined version of the target function. let mut new_ssa = self.builder.finish(); assert_eq!(new_ssa.functions.len(), 1); - new_ssa.functions.pop_first().unwrap().1 + let mut new_func = new_ssa.functions.pop_first().unwrap().1; + new_func.dfg.data_bus = databus; + new_func } /// Inlines a function into the current function and returns the translated return values diff --git a/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs b/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs index e5fffaccdd..ce205c8d88 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/mem2reg.rs @@ -91,6 +91,7 @@ impl Ssa { let mut context = PerFunctionContext::new(function); context.mem2reg(); context.remove_instructions(); + context.update_data_bus(); } self } @@ -326,7 +327,7 @@ impl<'f> PerFunctionContext<'f> { match typ { Type::Numeric(_) => false, Type::Function => false, - Type::Reference => true, + Type::Reference(_) => true, Type::Array(elements, _) | Type::Slice(elements) => { elements.iter().any(Self::contains_references) } @@ -362,6 +363,11 @@ impl<'f> PerFunctionContext<'f> { } } + fn update_data_bus(&mut self) { + let databus = self.inserter.function.dfg.data_bus.clone(); + self.inserter.function.dfg.data_bus = databus.map_values(|t| self.inserter.resolve(t)); + } + fn handle_terminator(&mut self, block: BasicBlockId, references: &mut Block) { self.inserter.map_terminator_in_place(block); @@ -427,7 +433,7 @@ mod tests { let func_id = Id::test_new(0); let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); - let v0 = builder.insert_allocate(); + let v0 = builder.insert_allocate(Type::Array(Rc::new(vec![Type::field()]), 2)); let one = builder.field_constant(FieldElement::one()); let two = builder.field_constant(FieldElement::one()); @@ -468,7 +474,7 @@ mod tests { let func_id = Id::test_new(0); let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); - let v0 = builder.insert_allocate(); + let v0 = builder.insert_allocate(Type::field()); let one = builder.field_constant(FieldElement::one()); builder.insert_store(v0, one); let v1 = builder.insert_load(v0, Type::field()); @@ -502,7 +508,7 @@ mod tests { let func_id = Id::test_new(0); let mut builder = FunctionBuilder::new("func".into(), func_id, RuntimeType::Acir); - let v0 = builder.insert_allocate(); + let v0 = builder.insert_allocate(Type::field()); let const_one = builder.field_constant(FieldElement::one()); builder.insert_store(v0, const_one); builder.terminate_with_return(vec![v0]); @@ -562,7 +568,7 @@ mod tests { let main_id = Id::test_new(0); let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); - let v0 = builder.insert_allocate(); + let v0 = builder.insert_allocate(Type::field()); let five = builder.field_constant(5u128); builder.insert_store(v0, five); @@ -642,12 +648,12 @@ mod tests { let main_id = Id::test_new(0); let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); - let v0 = builder.insert_allocate(); + let v0 = builder.insert_allocate(Type::field()); let zero = builder.field_constant(0u128); builder.insert_store(v0, zero); - let v2 = builder.insert_allocate(); + let v2 = builder.insert_allocate(Type::Reference(Rc::new(Type::field()))); builder.insert_store(v2, v0); let v3 = builder.insert_load(v2, Type::field()); diff --git a/compiler/noirc_evaluator/src/ssa/opt/mem2reg/block.rs b/compiler/noirc_evaluator/src/ssa/opt/mem2reg/block.rs index 22c5705b72..532785d292 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/mem2reg/block.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/mem2reg/block.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::BTreeMap}; +use std::borrow::Cow; use crate::ssa::ir::{ function::Function, @@ -19,27 +19,27 @@ pub(super) struct Block { /// Maps a ValueId to the Expression it represents. /// Multiple ValueIds can map to the same Expression, e.g. /// dereferences to the same allocation. - pub(super) expressions: BTreeMap, + pub(super) expressions: im::OrdMap, /// Each expression is tracked as to how many aliases it /// may have. If there is only 1, we can attempt to optimize /// out any known loads to that alias. Note that "alias" here /// includes the original reference as well. - pub(super) aliases: BTreeMap, + pub(super) aliases: im::OrdMap, /// Each allocate instruction result (and some reference block parameters) /// will map to a Reference value which tracks whether the last value stored /// to the reference is known. - pub(super) references: BTreeMap, + pub(super) references: im::OrdMap, /// The last instance of a `Store` instruction to each address in this block - pub(super) last_stores: BTreeMap, + pub(super) last_stores: im::OrdMap, } /// An `Expression` here is used to represent a canonical key /// into the aliases map since otherwise two dereferences of the /// same address will be given different ValueIds. -#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)] pub(super) enum Expression { Dereference(Box), ArrayElement(Box), @@ -111,10 +111,7 @@ impl Block { } fn invalidate_all_references(&mut self) { - for reference_value in self.references.values_mut() { - *reference_value = ReferenceValue::Unknown; - } - + self.references.clear(); self.last_stores.clear(); } @@ -137,7 +134,7 @@ impl Block { } // Keep only the references present in both maps. - let mut intersection = BTreeMap::new(); + let mut intersection = im::OrdMap::new(); for (value_id, reference) in &other.references { if let Some(existing) = self.references.get(value_id) { intersection.insert(*value_id, existing.unify(*reference)); diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 4879facd78..501a03bcb5 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -152,7 +152,8 @@ impl<'a> FunctionContext<'a> { /// Allocate a single slot of memory and store into it the given initial value of the variable. /// Always returns a Value::Mutable wrapping the allocate instruction. pub(super) fn new_mutable_variable(&mut self, value_to_store: ValueId) -> Value { - let alloc = self.builder.insert_allocate(); + let element_type = self.builder.current_function.dfg.type_of_value(value_to_store); + let alloc = self.builder.insert_allocate(element_type); self.builder.insert_store(alloc, value_to_store); let typ = self.builder.type_of_value(value_to_store); Value::Mutable(alloc, typ) @@ -177,7 +178,7 @@ impl<'a> FunctionContext<'a> { // A mutable reference wraps each element into a reference. // This can be multiple values if the element type is a tuple. ast::Type::MutableReference(element) => { - Self::map_type_helper(element, &mut |_| f(Type::Reference)) + Self::map_type_helper(element, &mut |typ| f(Type::Reference(Rc::new(typ)))) } ast::Type::FmtString(len, fields) => { // A format string is represented by multiple values @@ -231,8 +232,8 @@ impl<'a> FunctionContext<'a> { ast::Type::Slice(_) => panic!("convert_non_tuple_type called on a slice: {typ}"), ast::Type::MutableReference(element) => { // Recursive call to panic if element is a tuple - Self::convert_non_tuple_type(element); - Type::Reference + let element = Self::convert_non_tuple_type(element); + Type::Reference(Rc::new(element)) } } } @@ -274,16 +275,11 @@ impl<'a> FunctionContext<'a> { let bit_width = self.builder.numeric_constant(FieldElement::from(2_i128.pow(bit_size)), Type::field()); let sign_not = self.builder.insert_binary(one, BinaryOp::Sub, sign); - let as_field = - self.builder.insert_instruction(Instruction::Cast(input, Type::field()), None).first(); - let sign_field = - self.builder.insert_instruction(Instruction::Cast(sign, Type::field()), None).first(); + let as_field = self.builder.insert_cast(input, Type::field()); + let sign_field = self.builder.insert_cast(sign, Type::field()); let positive_predicate = self.builder.insert_binary(sign_field, BinaryOp::Mul, as_field); let two_complement = self.builder.insert_binary(bit_width, BinaryOp::Sub, as_field); - let sign_not_field = self - .builder - .insert_instruction(Instruction::Cast(sign_not, Type::field()), None) - .first(); + let sign_not_field = self.builder.insert_cast(sign_not, Type::field()); let negative_predicate = self.builder.insert_binary(sign_not_field, BinaryOp::Mul, two_complement); self.builder.insert_binary(positive_predicate, BinaryOp::Add, negative_predicate) @@ -314,17 +310,8 @@ impl<'a> FunctionContext<'a> { match operator { BinaryOpKind::Add | BinaryOpKind::Subtract => { // Result is computed modulo the bit size - let mut result = self - .builder - .insert_instruction( - Instruction::Truncate { - value: result, - bit_size, - max_bit_size: bit_size + 1, - }, - None, - ) - .first(); + let mut result = + self.builder.insert_truncate(result, bit_size, bit_size + 1); result = self.builder.insert_cast(result, Type::unsigned(bit_size)); self.check_signed_overflow(result, lhs, rhs, operator, bit_size, location); @@ -334,17 +321,7 @@ impl<'a> FunctionContext<'a> { // Result is computed modulo the bit size let mut result = self.builder.insert_cast(result, Type::unsigned(2 * bit_size)); - result = self - .builder - .insert_instruction( - Instruction::Truncate { - value: result, - bit_size, - max_bit_size: 2 * bit_size, - }, - None, - ) - .first(); + result = self.builder.insert_truncate(result, bit_size, 2 * bit_size); self.check_signed_overflow(result, lhs, rhs, operator, bit_size, location); self.builder.insert_cast(result, result_type) @@ -363,22 +340,19 @@ impl<'a> FunctionContext<'a> { BinaryOpKind::ShiftLeft => "left shift", _ => unreachable!("operator {} should not overflow", operator), }; - let message = format!("attempt to {} with overflow", op_name); - let range_constraint = Instruction::RangeCheck { - value: result, - max_bit_size: bit_size, - assert_message: Some(message), - }; - self.builder.set_location(location).insert_instruction(range_constraint, None); - if operator == BinaryOpKind::ShiftLeft { - match result_type { - Type::Numeric(NumericType::Signed { bit_size }) - | Type::Numeric(NumericType::Unsigned { bit_size }) => { - self.builder.insert_truncate(result, bit_size, bit_size + 1) - } - _ => result, - } + + if operator == BinaryOpKind::Multiply && bit_size == 1 { + result + } else if operator == BinaryOpKind::ShiftLeft { + self.check_left_shift_overflow(result, rhs, bit_size, location) } else { + let message = format!("attempt to {} with overflow", op_name); + let range_constraint = Instruction::RangeCheck { + value: result, + max_bit_size: bit_size, + assert_message: Some(message), + }; + self.builder.set_location(location).insert_instruction(range_constraint, None); result } } @@ -386,6 +360,30 @@ impl<'a> FunctionContext<'a> { } } + /// Overflow checks for shift-left + /// We use Rust behavior for shift left: + /// If rhs is more or equal than the bit size, then we overflow + /// If not, we do not overflow and shift left with 0 when bits are falling out of the bit size + fn check_left_shift_overflow( + &mut self, + result: ValueId, + rhs: ValueId, + bit_size: u32, + location: Location, + ) -> ValueId { + let max = self + .builder + .numeric_constant(FieldElement::from(bit_size as i128), Type::unsigned(bit_size)); + let overflow = self.builder.insert_binary(rhs, BinaryOp::Lt, max); + let one = self.builder.numeric_constant(FieldElement::one(), Type::bool()); + self.builder.set_location(location).insert_constrain( + overflow, + one, + Some("attempt to left shift with overflow".to_owned()), + ); + self.builder.insert_truncate(result, bit_size, bit_size + 1) + } + /// Insert constraints ensuring that the operation does not overflow the bit size of the result /// We assume that: /// lhs and rhs are signed integers of bit size bit_size @@ -456,17 +454,16 @@ impl<'a> FunctionContext<'a> { // Then we check the signed product fits in a signed integer of bit_size-bits let not_same = self.builder.insert_binary(one, BinaryOp::Sub, same_sign); - let not_same_sign_field = self - .builder - .insert_instruction(Instruction::Cast(not_same, Type::unsigned(bit_size)), None) - .first(); + let not_same_sign_field = + self.builder.insert_cast(not_same, Type::unsigned(bit_size)); let positive_maximum_with_offset = self.builder.insert_binary(half_width, BinaryOp::Add, not_same_sign_field); let product_overflow_check = self.builder.insert_binary(product, BinaryOp::Lt, positive_maximum_with_offset); - self.builder.set_location(location).insert_instruction( - Instruction::Constrain(product_overflow_check, one, Some(message)), - None, + self.builder.set_location(location).insert_constrain( + product_overflow_check, + one, + Some(message), ); } BinaryOpKind::ShiftLeft => unreachable!("shift is not supported for signed integer"), @@ -486,7 +483,15 @@ impl<'a> FunctionContext<'a> { location: Location, ) -> Values { let mut result = match operator { - BinaryOpKind::ShiftLeft => self.builder.insert_shift_left(lhs, rhs), + BinaryOpKind::ShiftLeft => { + let result_type = self.builder.current_function.dfg.type_of_value(lhs); + let bit_size = match result_type { + Type::Numeric(NumericType::Signed { bit_size }) + | Type::Numeric(NumericType::Unsigned { bit_size }) => bit_size, + _ => unreachable!("ICE: Truncation attempted on non-integer"), + }; + self.builder.insert_wrapping_shift_left(lhs, rhs, bit_size) + } BinaryOpKind::ShiftRight => self.builder.insert_shift_right(lhs, rhs), BinaryOpKind::Equal | BinaryOpKind::NotEqual if matches!(self.builder.type_of_value(lhs), Type::Array(..)) => @@ -573,7 +578,7 @@ impl<'a> FunctionContext<'a> { let loop_end = self.builder.insert_block(); // pre-loop - let result_alloc = self.builder.set_location(location).insert_allocate(); + let result_alloc = self.builder.set_location(location).insert_allocate(Type::bool()); let true_value = self.builder.numeric_constant(1u128, Type::bool()); self.builder.insert_store(result_alloc, true_value); let zero = self.builder.field_constant(0u128); diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index 7677f5669c..d7e6b8b0a3 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -1,4 +1,4 @@ -mod context; +pub(crate) mod context; mod program; mod value; @@ -9,12 +9,15 @@ use iter_extended::{try_vecmap, vecmap}; use noirc_errors::Location; use noirc_frontend::{ monomorphization::ast::{self, Binary, Expression, Program}, - BinaryOpKind, + BinaryOpKind, Visibility, }; use crate::{ errors::RuntimeError, - ssa::ir::{instruction::Intrinsic, types::NumericType}, + ssa::{ + function_builder::data_bus::DataBusBuilder, + ir::{instruction::Intrinsic, types::NumericType}, + }, }; use self::{ @@ -22,17 +25,25 @@ use self::{ value::{Tree, Values}, }; -use super::ir::{ - function::RuntimeType, - instruction::{BinaryOp, TerminatorInstruction}, - types::Type, - value::ValueId, +use super::{ + function_builder::data_bus::DataBus, + ir::{ + function::RuntimeType, + instruction::{BinaryOp, TerminatorInstruction}, + types::Type, + value::ValueId, + }, }; /// Generates SSA for the given monomorphized program. /// /// This function will generate the SSA but does not perform any optimizations on it. pub(crate) fn generate_ssa(program: Program) -> Result { + // see which parameter has call_data/return_data attribute + let is_databus = DataBusBuilder::is_databus(&program.main_function_signature); + + let is_return_data = matches!(program.return_visibility, Visibility::DataBus); + let return_location = program.return_location; let context = SharedContext::new(program); @@ -48,20 +59,41 @@ pub(crate) fn generate_ssa(program: Program) -> Result { if main.unconstrained { RuntimeType::Brillig } else { RuntimeType::Acir }, &context, ); + + // Generate the call_data bus from the relevant parameters. We create it *before* processing the function body + let call_data = function_context.builder.call_data_bus(is_databus); + function_context.codegen_function_body(&main.body)?; + let mut return_data = DataBusBuilder::new(); if let Some(return_location) = return_location { let block = function_context.builder.current_block(); - if function_context.builder.current_function.dfg[block].terminator().is_some() { - let return_instruction = - function_context.builder.current_function.dfg[block].unwrap_terminator_mut(); - match return_instruction { - TerminatorInstruction::Return { call_stack, .. } => { - call_stack.clear(); - call_stack.push_back(return_location); + if function_context.builder.current_function.dfg[block].terminator().is_some() + && is_return_data + { + // initialize the return_data bus from the return values + let return_data_values = + match function_context.builder.current_function.dfg[block].unwrap_terminator() { + TerminatorInstruction::Return { return_values, .. } => return_values.to_owned(), + _ => unreachable!("ICE - expect return on the last block"), + }; + + return_data = + function_context.builder.initialize_data_bus(&return_data_values, return_data); + } + let return_instruction = + function_context.builder.current_function.dfg[block].unwrap_terminator_mut(); + match return_instruction { + TerminatorInstruction::Return { return_values, call_stack } => { + call_stack.clear(); + call_stack.push_back(return_location); + // replace the returned values with the return data array + if let Some(return_data_bus) = return_data.databus { + return_values.clear(); + return_values.push(return_data_bus); } - _ => unreachable!("ICE - expect return on the last block"), } + _ => unreachable!("ICE - expect return on the last block"), } } @@ -74,6 +106,9 @@ pub(crate) fn generate_ssa(program: Program) -> Result { function_context.new_function(dest_id, function); function_context.codegen_function_body(&function.body)?; } + // we save the data bus inside the dfg + function_context.builder.current_function.dfg.data_bus = + DataBus::get_data_bus(call_data, return_data); Ok(function_context.builder.finish()) } @@ -189,8 +224,9 @@ impl<'a> FunctionContext<'a> { } fn codegen_string(&mut self, string: &str) -> Values { - let elements = - vecmap(string.as_bytes(), |byte| self.builder.field_constant(*byte as u128).into()); + let elements = vecmap(string.as_bytes(), |byte| { + self.builder.numeric_constant(*byte as u128, Type::unsigned(8)).into() + }); let typ = Self::convert_non_tuple_type(&ast::Type::String(elements.len() as u64)); self.codegen_array(elements, typ) } @@ -210,6 +246,13 @@ impl<'a> FunctionContext<'a> { for element in elements { element.for_each(|element| { let element = element.eval(self); + + // If we're referencing a sub-array in a larger nested array we need to + // increase the reference count of the sub array. This maintains a + // pessimistic reference count (since some are likely moved rather than shared) + // which is important for Brillig's copy on write optimization. This has no + // effect in ACIR code. + self.builder.increment_array_reference_count(element); array.push_back(element); }); } @@ -248,11 +291,12 @@ impl<'a> FunctionContext<'a> { Ok(self.codegen_reference(&unary.rhs)?.map(|rhs| { match rhs { value::Value::Normal(value) => { - let alloc = self.builder.insert_allocate(); + let rhs_type = self.builder.current_function.dfg.type_of_value(value); + let alloc = self.builder.insert_allocate(rhs_type); self.builder.insert_store(alloc, value); Tree::Leaf(value::Value::Normal(alloc)) } - // NOTE: The `.into()` here converts the Value::Mutable into + // The `.into()` here converts the Value::Mutable into // a Value::Normal so it is no longer automatically dereferenced. value::Value::Mutable(reference, _) => reference.into(), } @@ -300,6 +344,7 @@ impl<'a> FunctionContext<'a> { } else { (array_or_slice[0], None) }; + self.codegen_array_index( array, index_value, @@ -344,7 +389,13 @@ impl<'a> FunctionContext<'a> { } _ => unreachable!("must have array or slice but got {array_type}"), } - self.builder.insert_array_get(array, offset, typ).into() + + // Reference counting in brillig relies on us incrementing reference + // counts when nested arrays/slices are constructed or indexed. This + // has no effect in ACIR code. + let result = self.builder.insert_array_get(array, offset, typ); + self.builder.increment_array_reference_count(result); + result.into() })) } @@ -534,8 +585,12 @@ impl<'a> FunctionContext<'a> { arguments.append(&mut values); } - self.codegen_intrinsic_call_checks(function, &arguments, call.location); + // If an array is passed as an argument we increase its reference count + for argument in &arguments { + self.builder.increment_array_reference_count(*argument); + } + self.codegen_intrinsic_call_checks(function, &arguments, call.location); Ok(self.insert_call(function, arguments, &call.return_type, call.location)) } @@ -575,12 +630,18 @@ impl<'a> FunctionContext<'a> { fn codegen_let(&mut self, let_expr: &ast::Let) -> Result { let mut values = self.codegen_expression(&let_expr.expression)?; - if let_expr.mutable { - values = values.map(|value| { - let value = value.eval(self); - Tree::Leaf(self.new_mutable_variable(value)) - }); - } + values = values.map(|value| { + let value = value.eval(self); + + // Make sure to increment array reference counts on each let binding + self.builder.increment_array_reference_count(value); + + Tree::Leaf(if let_expr.mutable { + self.new_mutable_variable(value) + } else { + value::Value::Normal(value) + }) + }); self.define(let_expr.id, values); Ok(Self::unit_value()) diff --git a/compiler/noirc_frontend/Cargo.toml b/compiler/noirc_frontend/Cargo.toml index 246d6617c9..6f3c35a814 100644 --- a/compiler/noirc_frontend/Cargo.toml +++ b/compiler/noirc_frontend/Cargo.toml @@ -26,6 +26,3 @@ regex = "1.9.1" [dev-dependencies] strum = "0.24" strum_macros = "0.24" - -[features] -aztec = [] diff --git a/compiler/noirc_frontend/src/ast/expression.rs b/compiler/noirc_frontend/src/ast/expression.rs index d29e167094..c78deaf6db 100644 --- a/compiler/noirc_frontend/src/ast/expression.rs +++ b/compiler/noirc_frontend/src/ast/expression.rs @@ -50,7 +50,13 @@ impl ExpressionKind { } pub fn prefix(operator: UnaryOp, rhs: Expression) -> ExpressionKind { - ExpressionKind::Prefix(Box::new(PrefixExpression { operator, rhs })) + match (operator, &rhs) { + ( + UnaryOp::Minus, + Expression { kind: ExpressionKind::Literal(Literal::Integer(field, sign)), .. }, + ) => ExpressionKind::Literal(Literal::Integer(*field, !sign)), + _ => ExpressionKind::Prefix(Box::new(PrefixExpression { operator, rhs })), + } } pub fn array(contents: Vec) -> ExpressionKind { @@ -65,7 +71,7 @@ impl ExpressionKind { } pub fn integer(contents: FieldElement) -> ExpressionKind { - ExpressionKind::Literal(Literal::Integer(contents)) + ExpressionKind::Literal(Literal::Integer(contents, false)) } pub fn boolean(contents: bool) -> ExpressionKind { @@ -76,6 +82,10 @@ impl ExpressionKind { ExpressionKind::Literal(Literal::Str(contents)) } + pub fn raw_string(contents: String, hashes: u8) -> ExpressionKind { + ExpressionKind::Literal(Literal::RawStr(contents, hashes)) + } + pub fn format_string(contents: String) -> ExpressionKind { ExpressionKind::Literal(Literal::FmtStr(contents)) } @@ -96,7 +106,7 @@ impl ExpressionKind { }; match literal { - Literal::Integer(integer) => Some(*integer), + Literal::Integer(integer, _) => Some(*integer), _ => None, } } @@ -310,8 +320,9 @@ impl UnaryOp { pub enum Literal { Array(ArrayLiteral), Bool(bool), - Integer(FieldElement), + Integer(FieldElement, /*sign*/ bool), // false for positive integer and true for negative Str(String), + RawStr(String, u8), FmtStr(String), Unit, } @@ -505,8 +516,19 @@ impl Display for Literal { write!(f, "[{repeated_element}; {length}]") } Literal::Bool(boolean) => write!(f, "{}", if *boolean { "true" } else { "false" }), - Literal::Integer(integer) => write!(f, "{}", integer.to_u128()), + Literal::Integer(integer, sign) => { + if *sign { + write!(f, "-{}", integer.to_u128()) + } else { + write!(f, "{}", integer.to_u128()) + } + } Literal::Str(string) => write!(f, "\"{string}\""), + Literal::RawStr(string, num_hashes) => { + let hashes: String = + std::iter::once('#').cycle().take(*num_hashes as usize).collect(); + write!(f, "r{hashes}\"{string}\"{hashes}") + } Literal::FmtStr(string) => write!(f, "f\"{string}\""), Literal::Unit => write!(f, "()"), } diff --git a/compiler/noirc_frontend/src/ast/mod.rs b/compiler/noirc_frontend/src/ast/mod.rs index 7ce01f461e..5c10d3fe8f 100644 --- a/compiler/noirc_frontend/src/ast/mod.rs +++ b/compiler/noirc_frontend/src/ast/mod.rs @@ -15,6 +15,7 @@ pub use expression::*; pub use function::*; use noirc_errors::Span; +use serde::{Deserialize, Serialize}; pub use statement::*; pub use structure::*; pub use traits::*; @@ -41,6 +42,8 @@ pub enum UnresolvedTypeData { FormatString(UnresolvedTypeExpression, Box), Unit, + Parenthesized(Box), + /// A Named UnresolvedType can be a struct type or a type variable Named(Path, Vec), @@ -152,6 +155,7 @@ impl std::fmt::Display for UnresolvedTypeData { Unit => write!(f, "()"), Error => write!(f, "error"), Unspecified => write!(f, "unspecified"), + Parenthesized(typ) => write!(f, "({typ})"), } } } @@ -230,10 +234,13 @@ impl UnresolvedTypeExpression { fn from_expr_helper(expr: Expression) -> Result { match expr.kind { - ExpressionKind::Literal(Literal::Integer(int)) => match int.try_to_u64() { - Some(int) => Ok(UnresolvedTypeExpression::Constant(int, expr.span)), - None => Err(expr), - }, + ExpressionKind::Literal(Literal::Integer(int, sign)) => { + assert!(!sign, "Negative literal is not allowed here"); + match int.try_to_u64() { + Some(int) => Ok(UnresolvedTypeExpression::Constant(int, expr.span)), + None => Err(expr), + } + } ExpressionKind::Variable(path) => Ok(UnresolvedTypeExpression::Variable(path)), ExpressionKind::Prefix(prefix) if prefix.operator == UnaryOp::Minus => { let lhs = Box::new(UnresolvedTypeExpression::Constant(0, expr.span)); @@ -278,13 +285,16 @@ pub enum FunctionVisibility { PublicCrate, } -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] /// Represents whether the parameter is public or known only to the prover. pub enum Visibility { Public, // Constants are not allowed in the ABI for main at the moment. // Constant, Private, + /// DataBus is public input handled as private input. We use the fact that return values are properly computed by the program to avoid having them as public inputs + /// it is useful for recursion and is handled by the proving system. + DataBus, } impl std::fmt::Display for Visibility { @@ -292,6 +302,7 @@ impl std::fmt::Display for Visibility { match self { Self::Public => write!(f, "pub"), Self::Private => write!(f, "priv"), + Self::DataBus => write!(f, "databus"), } } } diff --git a/compiler/noirc_frontend/src/ast/statement.rs b/compiler/noirc_frontend/src/ast/statement.rs index 1ca4d3101a..73b1f68778 100644 --- a/compiler/noirc_frontend/src/ast/statement.rs +++ b/compiler/noirc_frontend/src/ast/statement.rs @@ -198,7 +198,11 @@ impl From for Expression { fn from(i: Ident) -> Expression { Expression { span: i.0.span(), - kind: ExpressionKind::Variable(Path { segments: vec![i], kind: PathKind::Plain }), + kind: ExpressionKind::Variable(Path { + span: i.span(), + segments: vec![i], + kind: PathKind::Plain, + }), } } } @@ -311,6 +315,7 @@ impl UseTree { pub struct Path { pub segments: Vec, pub kind: PathKind, + pub span: Span, } impl Path { @@ -330,18 +335,11 @@ impl Path { } pub fn from_ident(name: Ident) -> Path { - Path { segments: vec![name], kind: PathKind::Plain } + Path { span: name.span(), segments: vec![name], kind: PathKind::Plain } } pub fn span(&self) -> Span { - let mut segments = self.segments.iter(); - let first_segment = segments.next().expect("ice : cannot have an empty path"); - let mut span = first_segment.0.span(); - - for segment in segments { - span = span.merge(segment.0.span()); - } - span + self.span } pub fn last_segment(&self) -> Ident { @@ -545,8 +543,11 @@ impl ForRange { // array.len() let segments = vec![array_ident]; - let array_ident = - ExpressionKind::Variable(Path { segments, kind: PathKind::Plain }); + let array_ident = ExpressionKind::Variable(Path { + segments, + kind: PathKind::Plain, + span: array_span, + }); let end_range = ExpressionKind::MethodCall(Box::new(MethodCallExpression { object: Expression::new(array_ident.clone(), array_span), @@ -561,8 +562,11 @@ impl ForRange { // array[i] let segments = vec![Ident::new(index_name, array_span)]; - let index_ident = - ExpressionKind::Variable(Path { segments, kind: PathKind::Plain }); + let index_ident = ExpressionKind::Variable(Path { + segments, + kind: PathKind::Plain, + span: array_span, + }); let loop_element = ExpressionKind::Index(Box::new(IndexExpression { collection: Expression::new(array_ident, array_span), diff --git a/compiler/noirc_frontend/src/hir/aztec_library.rs b/compiler/noirc_frontend/src/hir/aztec_library.rs deleted file mode 100644 index 3b4703dc60..0000000000 --- a/compiler/noirc_frontend/src/hir/aztec_library.rs +++ /dev/null @@ -1,1001 +0,0 @@ -use acvm::FieldElement; -use iter_extended::vecmap; -use noirc_errors::Span; - -use crate::graph::CrateId; -use crate::hir::def_collector::errors::DefCollectorErrorKind; -use crate::hir_def::expr::{HirExpression, HirLiteral}; -use crate::hir_def::stmt::HirStatement; -use crate::node_interner::{NodeInterner, StructId}; -use crate::parser::SortedModule; -use crate::token::SecondaryAttribute; -use crate::{ - hir::Context, BlockExpression, CallExpression, CastExpression, Distinctness, Expression, - ExpressionKind, FunctionReturnType, Ident, IndexExpression, LetStatement, Literal, - MemberAccessExpression, MethodCallExpression, NoirFunction, Path, PathKind, Pattern, Statement, - UnresolvedType, UnresolvedTypeData, Visibility, -}; -use crate::{ - ForLoopStatement, ForRange, FunctionDefinition, FunctionVisibility, ImportStatement, - NoirStruct, Param, PrefixExpression, Signedness, StatementKind, StructType, Type, TypeImpl, - UnaryOp, -}; -use fm::FileId; - -use super::def_map::ModuleDefId; - -// -// Helper macros for creating noir ast nodes -// -fn ident(name: &str) -> Ident { - Ident::new(name.to_string(), Span::default()) -} - -fn ident_path(name: &str) -> Path { - Path::from_ident(ident(name)) -} - -fn path(ident: Ident) -> Path { - Path::from_ident(ident) -} - -fn expression(kind: ExpressionKind) -> Expression { - Expression::new(kind, Span::default()) -} - -fn variable(name: &str) -> Expression { - expression(ExpressionKind::Variable(ident_path(name))) -} - -fn variable_ident(identifier: Ident) -> Expression { - expression(ExpressionKind::Variable(path(identifier))) -} - -fn variable_path(path: Path) -> Expression { - expression(ExpressionKind::Variable(path)) -} - -fn method_call(object: Expression, method_name: &str, arguments: Vec) -> Expression { - expression(ExpressionKind::MethodCall(Box::new(MethodCallExpression { - object, - method_name: ident(method_name), - arguments, - }))) -} - -fn call(func: Expression, arguments: Vec) -> Expression { - expression(ExpressionKind::Call(Box::new(CallExpression { func: Box::new(func), arguments }))) -} - -fn pattern(name: &str) -> Pattern { - Pattern::Identifier(ident(name)) -} - -fn mutable(name: &str) -> Pattern { - Pattern::Mutable(Box::new(pattern(name)), Span::default()) -} - -fn mutable_assignment(name: &str, assigned_to: Expression) -> Statement { - make_statement(StatementKind::Let(LetStatement { - pattern: mutable(name), - r#type: make_type(UnresolvedTypeData::Unspecified), - expression: assigned_to, - })) -} - -fn mutable_reference(variable_name: &str) -> Expression { - expression(ExpressionKind::Prefix(Box::new(PrefixExpression { - operator: UnaryOp::MutableReference, - rhs: variable(variable_name), - }))) -} - -fn assignment(name: &str, assigned_to: Expression) -> Statement { - make_statement(StatementKind::Let(LetStatement { - pattern: pattern(name), - r#type: make_type(UnresolvedTypeData::Unspecified), - expression: assigned_to, - })) -} - -fn member_access(lhs: &str, rhs: &str) -> Expression { - expression(ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { - lhs: variable(lhs), - rhs: ident(rhs), - }))) -} - -macro_rules! chained_path { - ( $base:expr $(, $tail:expr)* ) => { - { - let mut base_path = ident_path($base); - $( - base_path.segments.push(ident($tail)); - )* - base_path - } - } -} - -macro_rules! chained_dep { - ( $base:expr $(, $tail:expr)* ) => { - { - let mut base_path = ident_path($base); - base_path.kind = PathKind::Dep; - $( - base_path.segments.push(ident($tail)); - )* - base_path - } - } -} - -fn cast(lhs: Expression, ty: UnresolvedTypeData) -> Expression { - expression(ExpressionKind::Cast(Box::new(CastExpression { lhs, r#type: make_type(ty) }))) -} - -fn make_type(typ: UnresolvedTypeData) -> UnresolvedType { - UnresolvedType { typ, span: None } -} - -fn index_array(array: Ident, index: &str) -> Expression { - expression(ExpressionKind::Index(Box::new(IndexExpression { - collection: variable_path(path(array)), - index: variable(index), - }))) -} - -fn index_array_variable(array: Expression, index: &str) -> Expression { - expression(ExpressionKind::Index(Box::new(IndexExpression { - collection: array, - index: variable(index), - }))) -} - -fn import(path: Path) -> ImportStatement { - ImportStatement { path, alias: None } -} - -// -// Create AST Nodes for Aztec -// - -/// Traverses every function in the ast, calling `transform_function` which -/// determines if further processing is required -pub(crate) fn transform( - mut ast: SortedModule, - crate_id: &CrateId, - context: &Context, -) -> Result { - // Usage -> mut ast -> aztec_library::transform(&mut ast) - - // Covers all functions in the ast - for submodule in ast.submodules.iter_mut().filter(|submodule| submodule.is_contract) { - if transform_module(&mut submodule.contents, crate_id, context)? { - check_for_aztec_dependency(crate_id, context)?; - include_relevant_imports(&mut submodule.contents); - } - } - Ok(ast) -} - -// -// Transform Hir Nodes for Aztec -// - -/// Completes the Hir with data gathered from type resolution -pub(crate) fn transform_hir(crate_id: &CrateId, context: &mut Context) { - transform_events(crate_id, context); -} - -/// Includes an import to the aztec library if it has not been included yet -fn include_relevant_imports(ast: &mut SortedModule) { - // Create the aztec import path using the assumed chained_dep! macro - let aztec_import_path = import(chained_dep!("aztec")); - - // Check if the aztec import already exists - let is_aztec_imported = - ast.imports.iter().any(|existing_import| existing_import.path == aztec_import_path.path); - - // If aztec is not imported, add the import at the beginning - if !is_aztec_imported { - ast.imports.insert(0, aztec_import_path); - } -} - -/// Creates an error alerting the user that they have not downloaded the Aztec-noir library -fn check_for_aztec_dependency( - crate_id: &CrateId, - context: &Context, -) -> Result<(), (DefCollectorErrorKind, FileId)> { - let crate_graph = &context.crate_graph[crate_id]; - let has_aztec_dependency = crate_graph.dependencies.iter().any(|dep| dep.as_name() == "aztec"); - if has_aztec_dependency { - Ok(()) - } else { - Err((DefCollectorErrorKind::AztecNotFound {}, crate_graph.root_file_id)) - } -} - -// Check to see if the user has defined a storage struct -fn check_for_storage_definition(module: &SortedModule) -> bool { - module.types.iter().any(|r#struct| r#struct.name.0.contents == "Storage") -} - -// Check if "compute_note_hash_and_nullifier(Field,Field,Field,[Field; N]) -> [Field; 4]" is defined -fn check_for_compute_note_hash_and_nullifier_definition(module: &SortedModule) -> bool { - module.functions.iter().any(|func| { - func.def.name.0.contents == "compute_note_hash_and_nullifier" - && func.def.parameters.len() == 4 - && func.def.parameters[0].typ.typ == UnresolvedTypeData::FieldElement - && func.def.parameters[1].typ.typ == UnresolvedTypeData::FieldElement - && func.def.parameters[2].typ.typ == UnresolvedTypeData::FieldElement - // checks if the 4th parameter is an array and the Box in - // Array(Option, Box) contains only fields - && match &func.def.parameters[3].typ.typ { - UnresolvedTypeData::Array(_, inner_type) => { - match inner_type.typ { - UnresolvedTypeData::FieldElement => true, - _ => false, - } - }, - _ => false, - } - // We check the return type the same way as we did the 4th parameter - && match &func.def.return_type { - FunctionReturnType::Default(_) => false, - FunctionReturnType::Ty(unresolved_type) => { - match &unresolved_type.typ { - UnresolvedTypeData::Array(_, inner_type) => { - match inner_type.typ { - UnresolvedTypeData::FieldElement => true, - _ => false, - } - }, - _ => false, - } - } - } - }) -} - -/// Checks if an attribute is a custom attribute with a specific name -fn is_custom_attribute(attr: &SecondaryAttribute, attribute_name: &str) -> bool { - if let SecondaryAttribute::Custom(custom_attr) = attr { - custom_attr.as_str() == attribute_name - } else { - false - } -} - -/// Determines if ast nodes are annotated with aztec attributes. -/// For annotated functions it calls the `transform` function which will perform the required transformations. -/// Returns true if an annotated node is found, false otherwise -fn transform_module( - module: &mut SortedModule, - crate_id: &CrateId, - context: &Context, -) -> Result { - let mut has_transformed_module = false; - - // Check for a user defined storage struct - let storage_defined = check_for_storage_definition(&module); - - if storage_defined && !check_for_compute_note_hash_and_nullifier_definition(&module) { - let crate_graph = &context.crate_graph[crate_id]; - return Err(( - DefCollectorErrorKind::AztecComputeNoteHashAndNullifierNotFound { - span: Span::default(), // Add a default span so we know which contract file the error originates from - }, - crate_graph.root_file_id, - )); - } - - for structure in module.types.iter() { - if structure.attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Event)) { - module.impls.push(generate_selector_impl(structure)); - has_transformed_module = true; - } - } - - for func in module.functions.iter_mut() { - for secondary_attribute in func.def.attributes.secondary.clone() { - if is_custom_attribute(&secondary_attribute, "aztec(private)") { - transform_function("Private", func, storage_defined); - has_transformed_module = true; - } else if is_custom_attribute(&secondary_attribute, "aztec(public)") { - transform_function("Public", func, storage_defined); - has_transformed_module = true; - } - } - // Add the storage struct to the beginning of the function if it is unconstrained in an aztec contract - if storage_defined && func.def.is_unconstrained { - transform_unconstrained(func); - has_transformed_module = true; - } - } - Ok(has_transformed_module) -} - -/// If it does, it will insert the following things: -/// - A new Input that is provided for a kernel app circuit, named: {Public/Private}ContextInputs -/// - Hashes all of the function input variables -/// - This instantiates a helper function -fn transform_function(ty: &str, func: &mut NoirFunction, storage_defined: bool) { - let context_name = format!("{}Context", ty); - let inputs_name = format!("{}ContextInputs", ty); - let return_type_name = format!("{}CircuitPublicInputs", ty); - - // Add access to the storage struct - if storage_defined { - let storage_def = abstract_storage(&ty.to_lowercase(), false); - func.def.body.0.insert(0, storage_def); - } - - // Insert the context creation as the first action - let create_context = create_context(&context_name, &func.def.parameters); - func.def.body.0.splice(0..0, (create_context).iter().cloned()); - - // Add the inputs to the params - let input = create_inputs(&inputs_name); - func.def.parameters.insert(0, input); - - // Abstract return types such that they get added to the kernel's return_values - if let Some(return_values) = abstract_return_values(func) { - func.def.body.0.push(return_values); - } - - // Push the finish method call to the end of the function - let finish_def = create_context_finish(); - func.def.body.0.push(finish_def); - - let return_type = create_return_type(&return_type_name); - func.def.return_type = return_type; - func.def.return_visibility = Visibility::Public; - - // Distinct return types are only required for private functions - // Public functions should have open auto-inferred - match ty { - "Private" => func.def.return_distinctness = Distinctness::Distinct, - "Public" => func.def.is_open = true, - _ => (), - } -} - -/// Transform Unconstrained -/// -/// Inserts the following code at the beginning of an unconstrained function -/// ```noir -/// let storage = Storage::init(Context::none()); -/// ``` -/// -/// This will allow developers to access their contract' storage struct in unconstrained functions -fn transform_unconstrained(func: &mut NoirFunction) { - func.def.body.0.insert(0, abstract_storage("Unconstrained", true)); -} - -fn collect_crate_structs(crate_id: &CrateId, context: &Context) -> Vec { - context - .def_map(crate_id) - .expect("ICE: Missing crate in def_map") - .modules() - .iter() - .flat_map(|(_, module)| { - module.type_definitions().filter_map(|typ| { - if let ModuleDefId::TypeId(struct_id) = typ { - Some(struct_id) - } else { - None - } - }) - }) - .collect() -} - -/// Substitutes the signature literal that was introduced in the selector method previously with the actual signature. -fn transform_event(struct_id: StructId, interner: &mut NodeInterner) { - let struct_type = interner.get_struct(struct_id); - let selector_id = interner - .lookup_method(&Type::Struct(struct_type, vec![]), struct_id, "selector", false) - .expect("Selector method not found"); - let selector_function = interner.function(&selector_id); - - let compute_selector_statement = interner.statement( - selector_function - .block(interner) - .statements() - .first() - .expect("Compute selector statement not found"), - ); - - let compute_selector_expression = match compute_selector_statement { - HirStatement::Expression(expression_id) => match interner.expression(&expression_id) { - HirExpression::Call(hir_call_expression) => Some(hir_call_expression), - _ => None, - }, - _ => None, - } - .expect("Compute selector statement is not a call expression"); - - let first_arg_id = compute_selector_expression - .arguments - .first() - .expect("Missing argument for compute selector"); - - match interner.expression(first_arg_id) { - HirExpression::Literal(HirLiteral::Str(signature)) - if signature == SIGNATURE_PLACEHOLDER => - { - let selector_literal_id = first_arg_id; - - let structure = interner.get_struct(struct_id); - let signature = event_signature(&structure.borrow()); - interner.update_expression(*selector_literal_id, |expr| { - *expr = HirExpression::Literal(HirLiteral::Str(signature.clone())); - }); - - // Also update the type! It might have a different length now than the placeholder. - interner.push_expr_type( - selector_literal_id, - Type::String(Box::new(Type::Constant(signature.len() as u64))), - ); - } - _ => unreachable!("Signature placeholder literal does not match"), - } -} - -fn transform_events(crate_id: &CrateId, context: &mut Context) { - for struct_id in collect_crate_structs(crate_id, context) { - let attributes = context.def_interner.struct_attributes(&struct_id); - if attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Event)) { - transform_event(struct_id, &mut context.def_interner); - } - } -} - -const SIGNATURE_PLACEHOLDER: &str = "SIGNATURE_PLACEHOLDER"; - -/// Generates the impl for an event selector -/// -/// Inserts the following code: -/// ```noir -/// impl SomeStruct { -/// fn selector() -> Field { -/// aztec::oracle::compute_selector::compute_selector("SIGNATURE_PLACEHOLDER") -/// } -/// } -/// ``` -/// -/// This allows developers to emit events without having to write the signature of the event every time they emit it. -/// The signature cannot be known at this point since types are not resolved yet, so we use a signature placeholder. -/// It'll get resolved after by transforming the HIR. -fn generate_selector_impl(structure: &NoirStruct) -> TypeImpl { - let struct_type = make_type(UnresolvedTypeData::Named(path(structure.name.clone()), vec![])); - - let selector_fun_body = BlockExpression(vec![make_statement(StatementKind::Expression(call( - variable_path(chained_path!("aztec", "selector", "compute_selector")), - vec![expression(ExpressionKind::Literal(Literal::Str(SIGNATURE_PLACEHOLDER.to_string())))], - )))]); - - let mut selector_fn_def = FunctionDefinition::normal( - &ident("selector"), - &vec![], - &[], - &selector_fun_body, - &[], - &FunctionReturnType::Ty(make_type(UnresolvedTypeData::FieldElement)), - ); - - selector_fn_def.visibility = FunctionVisibility::Public; - - // Seems to be necessary on contract modules - selector_fn_def.return_visibility = Visibility::Public; - - TypeImpl { - object_type: struct_type, - type_span: structure.span, - generics: vec![], - methods: vec![NoirFunction::normal(selector_fn_def)], - } -} - -/// Helper function that returns what the private context would look like in the ast -/// This should make it available to be consumed within aztec private annotated functions. -/// -/// The replaced code: -/// ```noir -/// /// Before -/// fn foo(inputs: PrivateContextInputs) { -/// // ... -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() { -/// // ... -/// } -pub(crate) fn create_inputs(ty: &str) -> Param { - let context_ident = ident("inputs"); - let context_pattern = Pattern::Identifier(context_ident); - let type_path = chained_path!("aztec", "abi", ty); - let context_type = make_type(UnresolvedTypeData::Named(type_path, vec![])); - let visibility = Visibility::Private; - - Param { pattern: context_pattern, typ: context_type, visibility, span: Span::default() } -} - -/// Creates the private context object to be accessed within the function, the parameters need to be extracted to be -/// appended into the args hash object. -/// -/// The replaced code: -/// ```noir -/// #[aztec(private)] -/// fn foo(structInput: SomeStruct, arrayInput: [u8; 10], fieldInput: Field) -> Field { -/// // Create the hasher object -/// let mut hasher = Hasher::new(); -/// -/// // struct inputs call serialize on them to add an array of fields -/// hasher.add_multiple(structInput.serialize()); -/// -/// // Array inputs are iterated over and each element is added to the hasher (as a field) -/// for i in 0..arrayInput.len() { -/// hasher.add(arrayInput[i] as Field); -/// } -/// // Field inputs are added to the hasher -/// hasher.add({ident}); -/// -/// // Create the context -/// // The inputs (injected by this `create_inputs`) and completed hash object are passed to the context -/// let mut context = PrivateContext::new(inputs, hasher.hash()); -/// } -/// ``` -fn create_context(ty: &str, params: &[Param]) -> Vec { - let mut injected_expressions: Vec = vec![]; - - // `let mut hasher = Hasher::new();` - let let_hasher = mutable_assignment( - "hasher", // Assigned to - call( - variable_path(chained_path!("aztec", "abi", "Hasher", "new")), // Path - vec![], // args - ), - ); - - // Completes: `let mut hasher = Hasher::new();` - injected_expressions.push(let_hasher); - - // Iterate over each of the function parameters, adding to them to the hasher - params.iter().for_each(|Param { pattern, typ, span: _, visibility: _ }| { - match pattern { - Pattern::Identifier(identifier) => { - // Match the type to determine the padding to do - let unresolved_type = &typ.typ; - let expression = match unresolved_type { - // `hasher.add_multiple({ident}.serialize())` - UnresolvedTypeData::Named(..) => add_struct_to_hasher(identifier), - UnresolvedTypeData::Array(_, arr_type) => { - add_array_to_hasher(identifier, &arr_type) - } - // `hasher.add({ident})` - UnresolvedTypeData::FieldElement => add_field_to_hasher(identifier), - // Add the integer to the hasher, casted to a field - // `hasher.add({ident} as Field)` - UnresolvedTypeData::Integer(..) | UnresolvedTypeData::Bool => { - add_cast_to_hasher(identifier) - } - _ => unreachable!("[Aztec Noir] Provided parameter type is not supported"), - }; - injected_expressions.push(expression); - } - _ => todo!(), // Maybe unreachable? - } - }); - - // Create the inputs to the context - let inputs_expression = variable("inputs"); - // `hasher.hash()` - let hash_call = method_call( - variable("hasher"), // variable - "hash", // method name - vec![], // args - ); - - // let mut context = {ty}::new(inputs, hash); - let let_context = mutable_assignment( - "context", // Assigned to - call( - variable_path(chained_path!("aztec", "context", ty, "new")), // Path - vec![inputs_expression, hash_call], // args - ), - ); - injected_expressions.push(let_context); - - // Return all expressions that will be injected by the hasher - injected_expressions -} - -/// Abstract Return Type -/// -/// This function intercepts the function's current return type and replaces it with pushes -/// To the kernel -/// -/// The replaced code: -/// ```noir -/// /// Before -/// #[aztec(private)] -/// fn foo() -> abi::PrivateCircuitPublicInputs { -/// // ... -/// let my_return_value: Field = 10; -/// context.return_values.push(my_return_value); -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() -> Field { -/// // ... -/// let my_return_value: Field = 10; -/// my_return_value -/// } -/// ``` -/// Similarly; Structs will be pushed to the context, after serialize() is called on them. -/// Arrays will be iterated over and each element will be pushed to the context. -/// Any primitive type that can be cast will be casted to a field and pushed to the context. -fn abstract_return_values(func: &NoirFunction) -> Option { - let current_return_type = func.return_type().typ; - let len = func.def.body.len(); - let last_statement = &func.def.body.0[len - 1]; - - // TODO: (length, type) => We can limit the size of the array returned to be limited by kernel size - // Doesn't need done until we have settled on a kernel size - // TODO: support tuples here and in inputs -> convert into an issue - - // Check if the return type is an expression, if it is, we can handle it - match last_statement { - Statement { kind: StatementKind::Expression(expression), .. } => { - match current_return_type { - // Call serialize on structs, push the whole array, calling push_array - UnresolvedTypeData::Named(..) => Some(make_struct_return_type(expression.clone())), - UnresolvedTypeData::Array(..) => Some(make_array_return_type(expression.clone())), - // Cast these types to a field before pushing - UnresolvedTypeData::Bool | UnresolvedTypeData::Integer(..) => { - Some(make_castable_return_type(expression.clone())) - } - UnresolvedTypeData::FieldElement => Some(make_return_push(expression.clone())), - _ => None, - } - } - _ => None, - } -} - -/// Abstract storage -/// -/// For private functions: -/// ```noir -/// #[aztec(private)] -/// fn lol() { -/// let storage = Storage::init(Context::private(context)); -/// } -/// ``` -/// -/// For public functions: -/// ```noir -/// #[aztec(public)] -/// fn lol() { -/// let storage = Storage::init(Context::public(context)); -/// } -/// ``` -/// -/// For unconstrained functions: -/// ```noir -/// unconstrained fn lol() { -/// let storage = Storage::init(Context::none()); -/// } -fn abstract_storage(typ: &str, unconstrained: bool) -> Statement { - let init_context_call = if unconstrained { - call( - variable_path(chained_path!("aztec", "context", "Context", "none")), // Path - vec![], // args - ) - } else { - call( - variable_path(chained_path!("aztec", "context", "Context", typ)), // Path - vec![mutable_reference("context")], // args - ) - }; - - assignment( - "storage", // Assigned to - call( - variable_path(chained_path!("Storage", "init")), // Path - vec![init_context_call], // args - ), - ) -} - -/// Context Return Values -/// -/// Creates an instance to the context return values -/// ```noir -/// `context.return_values` -/// ``` -fn context_return_values() -> Expression { - member_access("context", "return_values") -} - -fn make_statement(kind: StatementKind) -> Statement { - Statement { span: Span::default(), kind } -} - -/// Make return Push -/// -/// Translates to: -/// `context.return_values.push({push_value})` -fn make_return_push(push_value: Expression) -> Statement { - make_statement(StatementKind::Semi(method_call( - context_return_values(), - "push", - vec![push_value], - ))) -} - -/// Make Return push array -/// -/// Translates to: -/// `context.return_values.push_array({push_value})` -fn make_return_push_array(push_value: Expression) -> Statement { - make_statement(StatementKind::Semi(method_call( - context_return_values(), - "push_array", - vec![push_value], - ))) -} - -/// Make struct return type -/// -/// Translates to: -/// ```noir -/// `context.return_values.push_array({push_value}.serialize())` -fn make_struct_return_type(expression: Expression) -> Statement { - let serialized_call = method_call( - expression, // variable - "serialize", // method name - vec![], // args - ); - make_return_push_array(serialized_call) -} - -/// Make array return type -/// -/// Translates to: -/// ```noir -/// for i in 0..{ident}.len() { -/// context.return_values.push({ident}[i] as Field) -/// } -/// ``` -fn make_array_return_type(expression: Expression) -> Statement { - let inner_cast_expression = - cast(index_array_variable(expression.clone(), "i"), UnresolvedTypeData::FieldElement); - let assignment = make_statement(StatementKind::Semi(method_call( - context_return_values(), // variable - "push", // method name - vec![inner_cast_expression], - ))); - - create_loop_over(expression, vec![assignment]) -} - -/// Castable return type -/// -/// Translates to: -/// ```noir -/// context.return_values.push({ident} as Field) -/// ``` -fn make_castable_return_type(expression: Expression) -> Statement { - // Cast these types to a field before pushing - let cast_expression = cast(expression, UnresolvedTypeData::FieldElement); - make_return_push(cast_expression) -} - -/// Create Return Type -/// -/// Public functions return abi::PublicCircuitPublicInputs while -/// private functions return abi::PrivateCircuitPublicInputs -/// -/// This call constructs an ast token referencing the above types -/// The name is set in the function above `transform`, hence the -/// whole token name is passed in -/// -/// The replaced code: -/// ```noir -/// -/// /// Before -/// fn foo() -> abi::PrivateCircuitPublicInputs { -/// // ... -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() { -/// // ... -/// } -pub(crate) fn create_return_type(ty: &str) -> FunctionReturnType { - let return_path = chained_path!("aztec", "abi", ty); - - let ty = make_type(UnresolvedTypeData::Named(return_path, vec![])); - FunctionReturnType::Ty(ty) -} - -/// Create Context Finish -/// -/// Each aztec function calls `context.finish()` at the end of a function -/// to return values required by the kernel. -/// -/// The replaced code: -/// ```noir -/// /// Before -/// fn foo() -> abi::PrivateCircuitPublicInputs { -/// // ... -/// context.finish() -/// } -/// -/// /// After -/// #[aztec(private)] -/// fn foo() { -/// // ... -/// } -pub(crate) fn create_context_finish() -> Statement { - let method_call = method_call( - variable("context"), // variable - "finish", // method name - vec![], // args - ); - make_statement(StatementKind::Expression(method_call)) -} - -// -// Methods to create hasher inputs -// - -fn add_struct_to_hasher(identifier: &Ident) -> Statement { - // If this is a struct, we call serialize and add the array to the hasher - let serialized_call = method_call( - variable_path(path(identifier.clone())), // variable - "serialize", // method name - vec![], // args - ); - - make_statement(StatementKind::Semi(method_call( - variable("hasher"), // variable - "add_multiple", // method name - vec![serialized_call], // args - ))) -} - -fn create_loop_over(var: Expression, loop_body: Vec) -> Statement { - // If this is an array of primitive types (integers / fields) we can add them each to the hasher - // casted to a field - let span = var.span.clone(); - - // `array.len()` - let end_range_expression = method_call( - var, // variable - "len", // method name - vec![], // args - ); - - // What will be looped over - // - `hasher.add({ident}[i] as Field)` - let for_loop_block = expression(ExpressionKind::Block(BlockExpression(loop_body))); - - // `for i in 0..{ident}.len()` - make_statement(StatementKind::For(ForLoopStatement { - range: ForRange::Range( - expression(ExpressionKind::Literal(Literal::Integer(FieldElement::from(i128::from( - 0, - ))))), - end_range_expression, - ), - identifier: ident("i"), - block: for_loop_block, - span, - })) -} - -fn add_array_to_hasher(identifier: &Ident, arr_type: &UnresolvedType) -> Statement { - // If this is an array of primitive types (integers / fields) we can add them each to the hasher - // casted to a field - - // Wrap in the semi thing - does that mean ended with semi colon? - // `hasher.add({ident}[i] as Field)` - - let arr_index = index_array(identifier.clone(), "i"); - let (add_expression, hasher_method_name) = match arr_type.typ { - UnresolvedTypeData::Named(..) => { - let hasher_method_name = "add_multiple".to_owned(); - let call = method_call( - // All serialise on each element - arr_index, // variable - "serialize", // method name - vec![], // args - ); - (call, hasher_method_name) - } - _ => { - let hasher_method_name = "add".to_owned(); - let call = cast( - arr_index, // lhs - `ident[i]` - UnresolvedTypeData::FieldElement, // cast to - `as Field` - ); - (call, hasher_method_name) - } - }; - - let block_statement = make_statement(StatementKind::Semi(method_call( - variable("hasher"), // variable - &hasher_method_name, // method name - vec![add_expression], - ))); - - create_loop_over(variable_ident(identifier.clone()), vec![block_statement]) -} - -fn add_field_to_hasher(identifier: &Ident) -> Statement { - // `hasher.add({ident})` - let ident = variable_path(path(identifier.clone())); - make_statement(StatementKind::Semi(method_call( - variable("hasher"), // variable - "add", // method name - vec![ident], // args - ))) -} - -fn add_cast_to_hasher(identifier: &Ident) -> Statement { - // `hasher.add({ident} as Field)` - // `{ident} as Field` - let cast_operation = cast( - variable_path(path(identifier.clone())), // lhs - UnresolvedTypeData::FieldElement, // rhs - ); - - // `hasher.add({ident} as Field)` - make_statement(StatementKind::Semi(method_call( - variable("hasher"), // variable - "add", // method name - vec![cast_operation], // args - ))) -} - -/// Computes the aztec signature for a resolved type. -fn signature_of_type(typ: &Type) -> String { - match typ { - Type::Integer(Signedness::Signed, bit_size) => format!("i{}", bit_size), - Type::Integer(Signedness::Unsigned, bit_size) => format!("u{}", bit_size), - Type::FieldElement => "Field".to_owned(), - Type::Bool => "bool".to_owned(), - Type::Array(len, typ) => { - if let Type::Constant(len) = **len { - format!("[{};{len}]", signature_of_type(typ)) - } else { - unimplemented!("Cannot generate signature for array with length type {:?}", typ) - } - } - Type::Struct(def, args) => { - let fields = def.borrow().get_fields(args); - let fields = vecmap(fields, |(_, typ)| signature_of_type(&typ)); - format!("({})", fields.join(",")) - } - Type::Tuple(types) => { - let fields = vecmap(types, signature_of_type); - format!("({})", fields.join(",")) - } - _ => unimplemented!("Cannot generate signature for type {:?}", typ), - } -} - -/// Computes the signature for a resolved event type. -/// It has the form 'EventName(Field,(Field),[u8;2])' -fn event_signature(event: &StructType) -> String { - let fields = vecmap(event.get_fields(&[]), |(_, typ)| signature_of_type(&typ)); - format!("{}({})", event.name.0.contents, fields.join(",")) -} diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index ce1cf675a0..ae06179212 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -1,33 +1,33 @@ use super::dc_mod::collect_defs; use super::errors::{DefCollectorErrorKind, DuplicateType}; use crate::graph::CrateId; -use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleData, ModuleDefId, ModuleId}; +use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleId}; use crate::hir::resolution::errors::ResolverError; -use crate::hir::resolution::import::PathResolutionError; -use crate::hir::resolution::path_resolver::PathResolver; + +use crate::hir::resolution::import::{resolve_imports, ImportDirective}; use crate::hir::resolution::resolver::Resolver; use crate::hir::resolution::{ - import::{resolve_imports, ImportDirective}, - path_resolver::StandardPathResolver, + collect_impls, collect_trait_impls, path_resolver, resolve_free_functions, resolve_globals, + resolve_impls, resolve_structs, resolve_trait_by_path, resolve_trait_impls, resolve_traits, + resolve_type_aliases, }; use crate::hir::type_check::{type_check_func, TypeCheckError, TypeChecker}; use crate::hir::Context; -use crate::hir_def::traits::{Trait, TraitConstant, TraitFunction, TraitImpl, TraitType}; -use crate::node_interner::{ - FuncId, NodeInterner, StmtId, StructId, TraitId, TraitImplId, TypeAliasId, -}; + +use crate::macros_api::MacroProcessor; +use crate::node_interner::{FuncId, NodeInterner, StmtId, StructId, TraitId, TypeAliasId}; use crate::parser::{ParserError, SortedModule}; use crate::{ - ExpressionKind, Generics, Ident, LetStatement, Literal, NoirFunction, NoirStruct, NoirTrait, - NoirTypeAlias, Path, Shared, StructType, TraitItem, Type, TypeBinding, TypeVariableKind, - UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, + ExpressionKind, Ident, LetStatement, Literal, NoirFunction, NoirStruct, NoirTrait, + NoirTypeAlias, Path, PathKind, Type, UnresolvedGenerics, UnresolvedTraitConstraint, + UnresolvedType, }; use fm::FileId; use iter_extended::vecmap; use noirc_errors::{CustomDiagnostic, Span}; -use std::collections::{BTreeMap, HashMap, HashSet}; -use std::rc::Rc; +use std::collections::{BTreeMap, HashMap}; + use std::vec; /// Stores all of the unresolved functions in a particular file/mod @@ -82,6 +82,7 @@ pub struct UnresolvedTrait { pub module_id: LocalModuleId, pub crate_id: CrateId, pub trait_def: NoirTrait, + pub method_ids: HashMap, pub fns_with_default_impl: UnresolvedFunctions, } @@ -124,6 +125,16 @@ pub struct DefCollector { pub(crate) collected_traits_impls: Vec, } +/// Maps the type and the module id in which the impl is defined to the functions contained in that +/// impl along with the generics declared on the impl itself. This also contains the Span +/// of the object_type of the impl, used to issue an error if the object type fails to resolve. +/// +/// Note that because these are keyed by unresolved types, the impl map is one of the few instances +/// of HashMap rather than BTreeMap. For this reason, we should be careful not to iterate over it +/// since it would be non-deterministic. +pub(crate) type ImplMap = + HashMap<(UnresolvedType, LocalModuleId), Vec<(UnresolvedGenerics, Span, UnresolvedFunctions)>>; + #[derive(Debug, Clone)] pub enum CompilationError { ParseError(ParserError), @@ -166,16 +177,6 @@ impl From for CompilationError { } } -/// Maps the type and the module id in which the impl is defined to the functions contained in that -/// impl along with the generics declared on the impl itself. This also contains the Span -/// of the object_type of the impl, used to issue an error if the object type fails to resolve. -/// -/// Note that because these are keyed by unresolved types, the impl map is one of the few instances -/// of HashMap rather than BTreeMap. For this reason, we should be careful not to iterate over it -/// since it would be non-deterministic. -type ImplMap = - HashMap<(UnresolvedType, LocalModuleId), Vec<(UnresolvedGenerics, Span, UnresolvedFunctions)>>; - impl DefCollector { fn new(def_map: CrateDefMap) -> DefCollector { DefCollector { @@ -199,6 +200,7 @@ impl DefCollector { context: &mut Context, ast: SortedModule, root_file_id: FileId, + macro_processors: Vec<&dyn MacroProcessor>, ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; let crate_id = def_map.krate; @@ -211,7 +213,11 @@ impl DefCollector { let crate_graph = &context.crate_graph[crate_id]; for dep in crate_graph.dependencies.clone() { - errors.extend(CrateDefMap::collect_defs(dep.crate_id, context)); + errors.extend(CrateDefMap::collect_defs( + dep.crate_id, + context, + macro_processors.clone(), + )); let dep_def_root = context.def_map(&dep.crate_id).expect("ice: def map was just created").root; @@ -239,9 +245,20 @@ impl DefCollector { context, )); + let submodules = vecmap(def_collector.def_map.modules().iter(), |(index, _)| index); // Add the current crate to the collection of DefMaps context.def_maps.insert(crate_id, def_collector.def_map); + inject_prelude(crate_id, context, crate_root, &mut def_collector.collected_imports); + for submodule in submodules { + inject_prelude( + crate_id, + context, + LocalModuleId(submodule), + &mut def_collector.collected_imports, + ); + } + // Resolve unresolved imports collected from the crate let (resolved, unresolved_imports) = resolve_imports(crate_id, def_collector.collected_imports, &context.def_maps); @@ -260,8 +277,11 @@ impl DefCollector { for resolved_import in resolved { let name = resolved_import.name; for ns in resolved_import.resolved_namespace.iter_defs() { - let result = current_def_map.modules[resolved_import.module_scope.0] - .import(name.clone(), ns); + let result = current_def_map.modules[resolved_import.module_scope.0].import( + name.clone(), + ns, + resolved_import.is_prelude, + ); if let Err((first_def, second_def)) = result { let err = DefCollectorErrorKind::Duplicate { @@ -341,10 +361,9 @@ impl DefCollector { errors.extend(resolved_globals.errors); - // We run hir transformations before type checks - #[cfg(feature = "aztec")] - crate::hir::aztec_library::transform_hir(&crate_id, context); - + for macro_processor in macro_processors { + macro_processor.process_typed_ast(&crate_id, context); + } errors.extend(type_check_globals(&mut context.def_interner, resolved_globals.globals)); // Type check all of the functions in the crate @@ -355,262 +374,45 @@ impl DefCollector { } } -/// Go through the list of impls and add each function within to the scope -/// of the module defined by its type. -fn collect_impls( - context: &mut Context, +fn inject_prelude( crate_id: CrateId, - collected_impls: &ImplMap, -) -> Vec<(CompilationError, FileId)> { - let interner = &mut context.def_interner; - let def_maps = &mut context.def_maps; - let mut errors: Vec<(CompilationError, FileId)> = vec![]; - - for ((unresolved_type, module_id), methods) in collected_impls { - let path_resolver = - StandardPathResolver::new(ModuleId { local_id: *module_id, krate: crate_id }); - - let file = def_maps[&crate_id].file_id(*module_id); - - for (generics, span, unresolved) in methods { - let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); - resolver.add_generics(generics); - let typ = resolver.resolve_type(unresolved_type.clone()); - - errors.extend(take_errors(unresolved.file_id, resolver)); - - if let Some(struct_type) = get_struct_type(&typ) { - let struct_type = struct_type.borrow(); - - // `impl`s are only allowed on types defined within the current crate - if struct_type.id.krate() != crate_id { - let span = *span; - let type_name = struct_type.name.to_string(); - let error = DefCollectorErrorKind::ForeignImpl { span, type_name }; - errors.push((error.into(), unresolved.file_id)); - continue; - } - - // Grab the module defined by the struct type. Note that impls are a case - // where the module the methods are added to is not the same as the module - // they are resolved in. - let module = get_module_mut(def_maps, struct_type.id.module_id()); - - for (_, method_id, method) in &unresolved.functions { - // If this method was already declared, remove it from the module so it cannot - // be accessed with the `TypeName::method` syntax. We'll check later whether the - // object types in each method overlap or not. If they do, we issue an error. - // If not, that is specialization which is allowed. - if module.declare_function(method.name_ident().clone(), *method_id).is_err() { - module.remove_function(method.name_ident()); - } - } - // Prohibit defining impls for primitive types if we're not in the stdlib - } else if typ != Type::Error && !crate_id.is_stdlib() { - let span = *span; - let error = DefCollectorErrorKind::NonStructTypeInImpl { span }; - errors.push((error.into(), unresolved.file_id)); - } - } - } - errors -} - -fn get_module_mut( - def_maps: &mut BTreeMap, - module: ModuleId, -) -> &mut ModuleData { - &mut def_maps.get_mut(&module.krate).unwrap().modules[module.local_id.0] -} - -fn collect_trait_impl_methods( - interner: &mut NodeInterner, - def_maps: &BTreeMap, - crate_id: CrateId, - trait_id: TraitId, - trait_impl: &mut UnresolvedTraitImpl, -) -> Vec<(CompilationError, FileId)> { - // In this Vec methods[i] corresponds to trait.methods[i]. If the impl has no implementation - // for a particular method, the default implementation will be added at that slot. - let mut ordered_methods = Vec::new(); - - let the_trait = interner.get_trait(trait_id); - - // check whether the trait implementation is in the same crate as either the trait or the type - let mut errors = - check_trait_impl_crate_coherence(interner, &the_trait, trait_impl, crate_id, def_maps); - // set of function ids that have a corresponding method in the trait - let mut func_ids_in_trait = HashSet::new(); - - for method in &the_trait.methods { - let overrides: Vec<_> = trait_impl - .methods - .functions - .iter() - .filter(|(_, _, f)| f.name() == method.name.0.contents) - .collect(); - - if overrides.is_empty() { - if let Some(default_impl) = &method.default_impl { - let func_id = interner.push_empty_fn(); - let module = ModuleId { local_id: trait_impl.module_id, krate: crate_id }; - interner.push_function(func_id, &default_impl.def, module); - func_ids_in_trait.insert(func_id); - ordered_methods.push(( - method.default_impl_module_id, - func_id, - *default_impl.clone(), - )); - } else { - let error = DefCollectorErrorKind::TraitMissingMethod { - trait_name: the_trait.name.clone(), - method_name: method.name.clone(), - trait_impl_span: trait_impl.object_type.span.expect("type must have a span"), - }; - errors.push((error.into(), trait_impl.file_id)); - } - } else { - for (_, func_id, _) in &overrides { - func_ids_in_trait.insert(*func_id); - } - - if overrides.len() > 1 { - let error = DefCollectorErrorKind::Duplicate { - typ: DuplicateType::TraitAssociatedFunction, - first_def: overrides[0].2.name_ident().clone(), - second_def: overrides[1].2.name_ident().clone(), - }; - errors.push((error.into(), trait_impl.file_id)); - } - - ordered_methods.push(overrides[0].clone()); - } - } - - // Emit MethodNotInTrait error for methods in the impl block that - // don't have a corresponding method signature defined in the trait - for (_, func_id, func) in &trait_impl.methods.functions { - if !func_ids_in_trait.contains(func_id) { - let error = DefCollectorErrorKind::MethodNotInTrait { - trait_name: the_trait.name.clone(), - impl_method: func.name_ident().clone(), - }; - errors.push((error.into(), trait_impl.file_id)); - } - } + context: &Context, + crate_root: LocalModuleId, + collected_imports: &mut Vec, +) { + let segments: Vec<_> = "std::prelude" + .split("::") + .map(|segment| crate::Ident::new(segment.into(), Span::default())) + .collect(); - trait_impl.methods.functions = ordered_methods; - trait_impl.methods.trait_id = Some(trait_id); - errors -} + let path = + Path { segments: segments.clone(), kind: crate::PathKind::Dep, span: Span::default() }; -fn collect_trait_impl( - context: &mut Context, - crate_id: CrateId, - trait_impl: &mut UnresolvedTraitImpl, -) -> Vec<(CompilationError, FileId)> { - let interner = &mut context.def_interner; - let def_maps = &mut context.def_maps; - let mut errors: Vec<(CompilationError, FileId)> = vec![]; - let unresolved_type = trait_impl.object_type.clone(); - let module = ModuleId { local_id: trait_impl.module_id, krate: crate_id }; - trait_impl.trait_id = - match resolve_trait_by_path(def_maps, module, trait_impl.trait_path.clone()) { - Ok(trait_id) => Some(trait_id), - Err(error) => { - errors.push((error.into(), trait_impl.file_id)); - None - } - }; - - if let Some(trait_id) = trait_impl.trait_id { - errors - .extend(collect_trait_impl_methods(interner, def_maps, crate_id, trait_id, trait_impl)); - - let path_resolver = StandardPathResolver::new(module); - let file = def_maps[&crate_id].file_id(trait_impl.module_id); - let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); - resolver.add_generics(&trait_impl.generics); - let typ = resolver.resolve_type(unresolved_type); - errors.extend(take_errors(trait_impl.file_id, resolver)); - - if let Some(struct_type) = get_struct_type(&typ) { - let struct_type = struct_type.borrow(); - let module = get_module_mut(def_maps, struct_type.id.module_id()); - - for (_, method_id, method) in &trait_impl.methods.functions { - // If this method was already declared, remove it from the module so it cannot - // be accessed with the `TypeName::method` syntax. We'll check later whether the - // object types in each method overlap or not. If they do, we issue an error. - // If not, that is specialization which is allowed. - if module.declare_function(method.name_ident().clone(), *method_id).is_err() { - module.remove_function(method.name_ident()); - } + if !crate_id.is_stdlib() { + if let Ok(module_def) = path_resolver::resolve_path( + &context.def_maps, + ModuleId { krate: crate_id, local_id: crate_root }, + path, + ) { + let module_id = module_def.as_module().expect("std::prelude should be a module"); + let prelude = context.module(module_id).scope().names(); + + for path in prelude { + let mut segments = segments.clone(); + segments.push(Ident::new(path.to_string(), Span::default())); + + collected_imports.insert( + 0, + ImportDirective { + module_id: crate_root, + path: Path { segments, kind: PathKind::Dep, span: Span::default() }, + alias: None, + is_prelude: true, + }, + ); } } } - errors -} - -fn collect_trait_impls( - context: &mut Context, - crate_id: CrateId, - collected_impls: &mut [UnresolvedTraitImpl], -) -> Vec<(CompilationError, FileId)> { - collected_impls - .iter_mut() - .flat_map(|trait_impl| collect_trait_impl(context, crate_id, trait_impl)) - .collect() -} - -fn check_trait_impl_crate_coherence( - interner: &mut NodeInterner, - the_trait: &Trait, - trait_impl: &UnresolvedTraitImpl, - current_crate: CrateId, - def_maps: &BTreeMap, -) -> Vec<(CompilationError, FileId)> { - let mut errors: Vec<(CompilationError, FileId)> = vec![]; - - let module = ModuleId { krate: current_crate, local_id: trait_impl.module_id }; - let file = def_maps[¤t_crate].file_id(trait_impl.module_id); - let path_resolver = StandardPathResolver::new(module); - let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); - - let object_crate = match resolver.resolve_type(trait_impl.object_type.clone()) { - Type::Struct(struct_type, _) => struct_type.borrow().id.krate(), - _ => CrateId::Dummy, - }; - - if current_crate != the_trait.crate_id && current_crate != object_crate { - let error = DefCollectorErrorKind::TraitImplOrphaned { - span: trait_impl.object_type.span.expect("object type must have a span"), - }; - errors.push((error.into(), trait_impl.file_id)); - } - - errors -} - -fn resolve_trait_by_path( - def_maps: &BTreeMap, - module: ModuleId, - path: Path, -) -> Result { - let path_resolver = StandardPathResolver::new(module); - - match path_resolver.resolve(def_maps, path.clone()) { - Ok(ModuleDefId::TraitId(trait_id)) => Ok(trait_id), - Ok(_) => Err(DefCollectorErrorKind::NotATrait { not_a_trait_name: path }), - Err(_) => Err(DefCollectorErrorKind::TraitNotFound { trait_path: path }), - } -} - -fn get_struct_type(typ: &Type) -> Option<&Shared> { - match typ { - Type::Struct(definition, _) => Some(definition), - _ => None, - } } /// Separate the globals Vec into two. The first element in the tuple will be the @@ -625,50 +427,6 @@ fn filter_literal_globals( }) } -pub struct ResolvedGlobals { - pub globals: Vec<(FileId, StmtId)>, - pub errors: Vec<(CompilationError, FileId)>, -} - -impl ResolvedGlobals { - pub fn extend(&mut self, oth: Self) { - self.globals.extend(oth.globals); - self.errors.extend(oth.errors); - } -} - -fn resolve_globals( - context: &mut Context, - globals: Vec, - crate_id: CrateId, -) -> ResolvedGlobals { - let mut errors: Vec<(CompilationError, FileId)> = vec![]; - let globals = vecmap(globals, |global| { - let module_id = ModuleId { local_id: global.module_id, krate: crate_id }; - let path_resolver = StandardPathResolver::new(module_id); - let storage_slot = context.next_storage_slot(module_id); - - let mut resolver = Resolver::new( - &mut context.def_interner, - &path_resolver, - &context.def_maps, - global.file_id, - ); - - let name = global.stmt_def.pattern.name_ident().clone(); - - let hir_stmt = resolver.resolve_global_let(global.stmt_def); - errors.extend(take_errors(global.file_id, resolver)); - - context.def_interner.update_global(global.stmt_id, hir_stmt); - - context.def_interner.push_global(global.stmt_id, name, global.module_id, storage_slot); - - (global.file_id, global.stmt_id) - }); - ResolvedGlobals { globals, errors } -} - fn type_check_globals( interner: &mut NodeInterner, global_ids: Vec<(FileId, StmtId)>, @@ -701,372 +459,23 @@ fn type_check_functions( .collect() } -/// Create the mappings from TypeId -> StructType -/// so that expressions can access the fields of structs -fn resolve_structs( - context: &mut Context, - structs: BTreeMap, - crate_id: CrateId, -) -> Vec<(CompilationError, FileId)> { - let mut errors: Vec<(CompilationError, FileId)> = vec![]; - // Resolve each field in each struct. - // Each struct should already be present in the NodeInterner after def collection. - for (type_id, typ) in structs { - let file_id = typ.file_id; - let (generics, fields, resolver_errors) = resolve_struct_fields(context, crate_id, typ); - errors.extend(vecmap(resolver_errors, |err| (err.into(), file_id))); - context.def_interner.update_struct(type_id, |struct_def| { - struct_def.set_fields(fields); - struct_def.generics = generics; - }); - } - errors -} - -fn resolve_trait_types( - _context: &mut Context, - _crate_id: CrateId, - _unresolved_trait: &UnresolvedTrait, -) -> (Vec, Vec<(CompilationError, FileId)>) { - // TODO - (vec![], vec![]) -} -fn resolve_trait_constants( - _context: &mut Context, - _crate_id: CrateId, - _unresolved_trait: &UnresolvedTrait, -) -> (Vec, Vec<(CompilationError, FileId)>) { - // TODO - (vec![], vec![]) -} - -fn resolve_trait_methods( - context: &mut Context, - trait_id: TraitId, - crate_id: CrateId, - unresolved_trait: &UnresolvedTrait, -) -> (Vec, Vec<(CompilationError, FileId)>) { - let interner = &mut context.def_interner; - let def_maps = &mut context.def_maps; - - let path_resolver = StandardPathResolver::new(ModuleId { - local_id: unresolved_trait.module_id, - krate: crate_id, - }); - let file = def_maps[&crate_id].file_id(unresolved_trait.module_id); - - let mut res = vec![]; - let mut resolver_errors = vec![]; - for item in &unresolved_trait.trait_def.items { - if let TraitItem::Function { - name, - generics, - parameters, - return_type, - where_clause: _, - body: _, - } = item - { - let the_trait = interner.get_trait(trait_id); - let self_type = - Type::TypeVariable(the_trait.self_type_typevar.clone(), TypeVariableKind::Normal); - - let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); - resolver.add_generics(generics); - resolver.set_self_type(Some(self_type)); - - let arguments = vecmap(parameters, |param| resolver.resolve_type(param.1.clone())); - let resolved_return_type = resolver.resolve_type(return_type.get_type().into_owned()); - let generics = resolver.get_generics().to_vec(); - - let name = name.clone(); - let span: Span = name.span(); - let default_impl_list: Vec<_> = unresolved_trait - .fns_with_default_impl - .functions - .iter() - .filter(|(_, _, q)| q.name() == name.0.contents) - .collect(); - let default_impl = if default_impl_list.len() == 1 { - Some(Box::new(default_impl_list[0].2.clone())) - } else { - None - }; - - let f = TraitFunction { - name, - generics, - arguments, - return_type: resolved_return_type, - span, - default_impl, - default_impl_file_id: unresolved_trait.file_id, - default_impl_module_id: unresolved_trait.module_id, - }; - res.push(f); - resolver_errors.extend(take_errors_filter_self_not_resolved(file, resolver)); - } - } - (res, resolver_errors) -} - -fn take_errors_filter_self_not_resolved( - file_id: FileId, - resolver: Resolver<'_>, -) -> Vec<(CompilationError, FileId)> { - resolver - .take_errors() - .iter() - .filter(|resolution_error| match resolution_error { - ResolverError::PathResolutionError(PathResolutionError::Unresolved(ident)) => { - &ident.0.contents != "Self" - } - _ => true, - }) - .cloned() - .map(|resolution_error| (resolution_error.into(), file_id)) - .collect() -} - -fn take_errors(file_id: FileId, resolver: Resolver<'_>) -> Vec<(CompilationError, FileId)> { - vecmap(resolver.take_errors(), |e| (e.into(), file_id)) -} - -/// Create the mappings from TypeId -> TraitType -/// so that expressions can access the elements of traits -fn resolve_traits( - context: &mut Context, - traits: BTreeMap, - crate_id: CrateId, -) -> Vec<(CompilationError, FileId)> { - for (trait_id, unresolved_trait) in &traits { - context.def_interner.push_empty_trait(*trait_id, unresolved_trait); - } - let mut res: Vec<(CompilationError, FileId)> = vec![]; - for (trait_id, unresolved_trait) in traits { - // Resolve order - // 1. Trait Types ( Trait constants can have a trait type, therefore types before constants) - let _ = resolve_trait_types(context, crate_id, &unresolved_trait); - // 2. Trait Constants ( Trait's methods can use trait types & constants, therefore they should be after) - let _ = resolve_trait_constants(context, crate_id, &unresolved_trait); - // 3. Trait Methods - let (methods, errors) = - resolve_trait_methods(context, trait_id, crate_id, &unresolved_trait); - res.extend(errors); - context.def_interner.update_trait(trait_id, |trait_def| { - trait_def.set_methods(methods); - }); - } - res -} - -fn resolve_struct_fields( - context: &mut Context, - krate: CrateId, - unresolved: UnresolvedStruct, -) -> (Generics, Vec<(Ident, Type)>, Vec) { - let path_resolver = - StandardPathResolver::new(ModuleId { local_id: unresolved.module_id, krate }); - let file_id = unresolved.file_id; - let (generics, fields, errors) = - Resolver::new(&mut context.def_interner, &path_resolver, &context.def_maps, file_id) - .resolve_struct_fields(unresolved.struct_def); - (generics, fields, errors) -} - -fn resolve_type_aliases( - context: &mut Context, - type_aliases: BTreeMap, - crate_id: CrateId, -) -> Vec<(CompilationError, FileId)> { - let mut errors: Vec<(CompilationError, FileId)> = vec![]; - for (type_id, unresolved_typ) in type_aliases { - let path_resolver = StandardPathResolver::new(ModuleId { - local_id: unresolved_typ.module_id, - krate: crate_id, - }); - let file = unresolved_typ.file_id; - let (typ, generics, resolver_errors) = - Resolver::new(&mut context.def_interner, &path_resolver, &context.def_maps, file) - .resolve_type_aliases(unresolved_typ.type_alias_def); - errors.extend(resolver_errors.iter().cloned().map(|e| (e.into(), file))); - context.def_interner.set_type_alias(type_id, typ, generics); - } - errors -} - -fn resolve_impls( - interner: &mut NodeInterner, - crate_id: CrateId, - def_maps: &BTreeMap, - collected_impls: ImplMap, - errors: &mut Vec<(CompilationError, FileId)>, -) -> Vec<(FileId, FuncId)> { - let mut file_method_ids = Vec::new(); - - for ((unresolved_type, module_id), methods) in collected_impls { - let path_resolver = - StandardPathResolver::new(ModuleId { local_id: module_id, krate: crate_id }); - - let file = def_maps[&crate_id].file_id(module_id); - - for (generics, _, functions) in methods { - let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); - resolver.add_generics(&generics); - let generics = resolver.get_generics().to_vec(); - let self_type = resolver.resolve_type(unresolved_type.clone()); - - let mut file_func_ids = resolve_function_set( - interner, - crate_id, - def_maps, - functions, - Some(self_type.clone()), - None, - generics, - errors, - ); - if self_type != Type::Error { - for (file_id, method_id) in &file_func_ids { - let method_name = interner.function_name(method_id).to_owned(); - - if let Some(first_fn) = - interner.add_method(&self_type, method_name.clone(), *method_id, false) - { - let error = ResolverError::DuplicateDefinition { - name: method_name, - first_span: interner.function_ident(&first_fn).span(), - second_span: interner.function_ident(method_id).span(), - }; - errors.push((error.into(), *file_id)); - } - } - } - file_method_ids.append(&mut file_func_ids); - } - } - - file_method_ids -} - -fn resolve_trait_impls( - context: &mut Context, - traits: Vec, - crate_id: CrateId, - errors: &mut Vec<(CompilationError, FileId)>, -) -> Vec<(FileId, FuncId)> { - let interner = &mut context.def_interner; - let mut methods = Vec::<(FileId, FuncId)>::new(); - - for trait_impl in traits { - let unresolved_type = trait_impl.object_type; - let local_mod_id = trait_impl.module_id; - let module_id = ModuleId { krate: crate_id, local_id: local_mod_id }; - let path_resolver = StandardPathResolver::new(module_id); - - let self_type_span = unresolved_type.span; - - let mut resolver = - Resolver::new(interner, &path_resolver, &context.def_maps, trait_impl.file_id); - resolver.add_generics(&trait_impl.generics); - let self_type = resolver.resolve_type(unresolved_type.clone()); - let generics = resolver.get_generics().to_vec(); - - let impl_id = interner.next_trait_impl_id(); - - let mut impl_methods = resolve_function_set( - interner, - crate_id, - &context.def_maps, - trait_impl.methods.clone(), - Some(self_type.clone()), - Some(impl_id), - generics.clone(), - errors, - ); - - let maybe_trait_id = trait_impl.trait_id; - if let Some(trait_id) = maybe_trait_id { - for (_, func) in &impl_methods { - interner.set_function_trait(*func, self_type.clone(), trait_id); - } - } - - if matches!(self_type, Type::MutableReference(_)) { - let span = self_type_span.unwrap_or_else(|| trait_impl.trait_path.span()); - let error = DefCollectorErrorKind::MutableReferenceInTraitImpl { span }; - errors.push((error.into(), trait_impl.file_id)); - } - - let mut new_resolver = - Resolver::new(interner, &path_resolver, &context.def_maps, trait_impl.file_id); - - new_resolver.set_generics(generics); - new_resolver.set_self_type(Some(self_type.clone())); - - if let Some(trait_id) = maybe_trait_id { - check_methods_signatures( - &mut new_resolver, - &impl_methods, - trait_id, - trait_impl.generics.len(), - errors, - ); - - let where_clause = trait_impl - .where_clause - .into_iter() - .flat_map(|item| new_resolver.resolve_trait_constraint(item)) - .collect(); - - let resolved_trait_impl = Shared::new(TraitImpl { - ident: trait_impl.trait_path.last_segment().clone(), - typ: self_type.clone(), - trait_id, - file: trait_impl.file_id, - where_clause, - methods: vecmap(&impl_methods, |(_, func_id)| *func_id), - }); - - if let Err((prev_span, prev_file)) = interner.add_trait_implementation( - self_type.clone(), - trait_id, - impl_id, - resolved_trait_impl, - ) { - let error = DefCollectorErrorKind::OverlappingImpl { - typ: self_type.clone(), - span: self_type_span.unwrap_or_else(|| trait_impl.trait_path.span()), - }; - errors.push((error.into(), trait_impl.file_id)); - - // The 'previous impl defined here' note must be a separate error currently - // since it may be in a different file and all errors have the same file id. - let error = DefCollectorErrorKind::OverlappingImplNote { span: prev_span }; - errors.push((error.into(), prev_file)); - } - - methods.append(&mut impl_methods); - } - } - - methods -} - // TODO(vitkov): Move this out of here and into type_check -fn check_methods_signatures( +pub(crate) fn check_methods_signatures( resolver: &mut Resolver, impl_methods: &Vec<(FileId, FuncId)>, trait_id: TraitId, trait_impl_generic_count: usize, errors: &mut Vec<(CompilationError, FileId)>, ) { - let the_trait = resolver.interner.get_trait(trait_id); - - let self_type = resolver.get_self_type().expect("trait impl must have a Self type"); + let self_type = resolver.get_self_type().expect("trait impl must have a Self type").clone(); // Temporarily bind the trait's Self type to self_type so we can type check - let _ = the_trait.self_type_typevar.borrow_mut().bind_to(self_type.clone(), the_trait.span); + let the_trait = resolver.interner.get_trait_mut(trait_id); + the_trait.self_type_typevar.bind(self_type); + + // Temporarily take the trait's methods so we can use both them and a mutable reference + // to the interner within the loop. + let trait_methods = std::mem::take(&mut the_trait.methods); for (file_id, func_id) in impl_methods { let impl_method = resolver.interner.function_meta(func_id); @@ -1078,19 +487,22 @@ fn check_methods_signatures( // If that's the case, a `MethodNotInTrait` error has already been thrown, and we can ignore // the impl method, since there's nothing in the trait to match its signature against. if let Some(trait_method) = - the_trait.methods.iter().find(|method| method.name.0.contents == func_name) + trait_methods.iter().find(|method| method.name.0.contents == func_name) { let impl_function_type = impl_method.typ.instantiate(resolver.interner); let impl_method_generic_count = impl_method.typ.generic_count() - trait_impl_generic_count; - let trait_method_generic_count = trait_method.generics.len(); + + // We subtract 1 here to account for the implicit generic `Self` type that is on all + // traits (and thus trait methods) but is not required (or allowed) for users to specify. + let trait_method_generic_count = trait_method.generics().len() - 1; if impl_method_generic_count != trait_method_generic_count { let error = DefCollectorErrorKind::MismatchTraitImplementationNumGenerics { impl_method_generic_count, trait_method_generic_count, - trait_name: the_trait.name.to_string(), + trait_name: resolver.interner.get_trait(trait_id).name.to_string(), method_name: func_name.to_string(), span: impl_method.location.span, }; @@ -1098,9 +510,9 @@ fn check_methods_signatures( } if let Type::Function(impl_params, _, _) = impl_function_type.0 { - if trait_method.arguments.len() == impl_params.len() { + if trait_method.arguments().len() == impl_params.len() { // Check the parameters of the impl method against the parameters of the trait method - let args = trait_method.arguments.iter(); + let args = trait_method.arguments().iter(); let args_and_params = args.zip(&impl_params).zip(&impl_method.parameters.0); for (parameter_index, ((expected, actual), (hir_pattern, _, _))) in @@ -1119,8 +531,8 @@ fn check_methods_signatures( } else { let error = DefCollectorErrorKind::MismatchTraitImplementationNumParameters { actual_num_parameters: impl_method.parameters.0.len(), - expected_num_parameters: trait_method.arguments.len(), - trait_name: the_trait.name.to_string(), + expected_num_parameters: trait_method.arguments().len(), + trait_name: resolver.interner.get_trait(trait_id).name.to_string(), method_name: func_name.to_string(), span: impl_method.location.span, }; @@ -1132,11 +544,12 @@ fn check_methods_signatures( let resolved_return_type = resolver.resolve_type(impl_method.return_type.get_type().into_owned()); - trait_method.return_type.unify(&resolved_return_type, &mut typecheck_errors, || { + // TODO: This is not right since it may bind generic return types + trait_method.return_type().unify(&resolved_return_type, &mut typecheck_errors, || { let ret_type_span = impl_method.return_type.get_type().span; let expr_span = ret_type_span.expect("return type must always have a span"); - let expected_typ = trait_method.return_type.to_string(); + let expected_typ = trait_method.return_type().to_string(); let expr_typ = impl_method.return_type().to_string(); TypeCheckError::TypeMismatch { expr_typ, expected_typ, expr_span } }); @@ -1145,74 +558,7 @@ fn check_methods_signatures( } } - the_trait.self_type_typevar.borrow_mut().unbind(the_trait.self_type_typevar_id); -} - -fn resolve_free_functions( - interner: &mut NodeInterner, - crate_id: CrateId, - def_maps: &BTreeMap, - collected_functions: Vec, - self_type: Option, - errors: &mut Vec<(CompilationError, FileId)>, -) -> Vec<(FileId, FuncId)> { - // Lower each function in the crate. This is now possible since imports have been resolved - collected_functions - .into_iter() - .flat_map(|unresolved_functions| { - resolve_function_set( - interner, - crate_id, - def_maps, - unresolved_functions, - self_type.clone(), - None, - vec![], // no impl generics - errors, - ) - }) - .collect() -} - -#[allow(clippy::too_many_arguments)] -fn resolve_function_set( - interner: &mut NodeInterner, - crate_id: CrateId, - def_maps: &BTreeMap, - mut unresolved_functions: UnresolvedFunctions, - self_type: Option, - trait_impl_id: Option, - impl_generics: Vec<(Rc, Shared, Span)>, - errors: &mut Vec<(CompilationError, FileId)>, -) -> Vec<(FileId, FuncId)> { - let file_id = unresolved_functions.file_id; - - let where_clause_errors = - unresolved_functions.resolve_trait_bounds_trait_ids(def_maps, crate_id); - errors.extend(where_clause_errors.iter().cloned().map(|e| (e.into(), file_id))); - - vecmap(unresolved_functions.functions, |(mod_id, func_id, func)| { - let module_id = ModuleId { krate: crate_id, local_id: mod_id }; - let path_resolver = StandardPathResolver::new(module_id); - - let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file_id); - // Must use set_generics here to ensure we re-use the same generics from when - // the impl was originally collected. Otherwise the function will be using different - // TypeVariables for the same generic, causing it to instantiate incorrectly. - resolver.set_generics(impl_generics.clone()); - resolver.set_self_type(self_type.clone()); - resolver.set_trait_id(unresolved_functions.trait_id); - resolver.set_trait_impl_id(trait_impl_id); - - // Without this, impl methods can accidentally be placed in contracts. See #3254 - if self_type.is_some() { - resolver.set_in_contract(false); - } - - let (hir_func, func_meta, errs) = resolver.resolve_function(func, func_id); - interner.push_fn_meta(func_meta, func_id); - interner.update_fn(func_id, hir_func); - errors.extend(errs.iter().cloned().map(|e| (e.into(), file_id))); - (file_id, func_id) - }) + let the_trait = resolver.interner.get_trait_mut(trait_id); + the_trait.set_methods(trait_methods); + the_trait.self_type_typevar.unbind(the_trait.self_type_typevar_id); } diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 17aa5e9951..aa1c658bad 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -1,4 +1,4 @@ -use std::vec; +use std::{collections::HashMap, vec}; use acvm::acir::acir_field::FieldOptions; use fm::FileId; @@ -44,6 +44,7 @@ pub fn collect_defs( ) -> Vec<(CompilationError, FileId)> { let mut collector = ModCollector { def_collector, file_id, module_id }; let mut errors: Vec<(CompilationError, FileId)> = vec![]; + // First resolve the module declarations for decl in ast.module_decls { errors.extend(collector.parse_module_declaration(context, &decl, crate_id)); @@ -57,6 +58,7 @@ pub fn collect_defs( module_id: collector.module_id, path: import.path, alias: import.alias, + is_prelude: false, }); } @@ -126,7 +128,8 @@ impl<'a> ModCollector<'a> { for method in r#impl.methods { let func_id = context.def_interner.push_empty_fn(); - context.def_interner.push_function(func_id, &method.def, module_id); + let location = Location::new(method.span(), self.file_id); + context.def_interner.push_function(func_id, &method.def, module_id, location); unresolved_functions.push_fn(self.module_id, func_id, method); } @@ -152,7 +155,8 @@ impl<'a> ModCollector<'a> { for (_, func_id, noir_function) in &mut unresolved_functions.functions { noir_function.def.where_clause.append(&mut trait_impl.where_clause.clone()); - context.def_interner.push_function(*func_id, &noir_function.def, module); + let location = Location::new(noir_function.def.span, self.file_id); + context.def_interner.push_function(*func_id, &noir_function.def, module, location); } let unresolved_trait_impl = UnresolvedTraitImpl { @@ -185,7 +189,8 @@ impl<'a> ModCollector<'a> { for item in &trait_impl.items { if let TraitImplItem::Function(impl_method) = item { let func_id = context.def_interner.push_empty_fn(); - context.def_interner.push_function(func_id, &impl_method.def, module); + let location = Location::new(impl_method.span(), self.file_id); + context.def_interner.push_function(func_id, &impl_method.def, module, location); unresolved_functions.push_fn(self.module_id, func_id, impl_method.clone()); } } @@ -218,7 +223,8 @@ impl<'a> ModCollector<'a> { // First create dummy function in the DefInterner // So that we can get a FuncId - context.def_interner.push_function(func_id, &function.def, module); + let location = Location::new(function.span(), self.file_id); + context.def_interner.push_function(func_id, &function.def, module, location); // Now link this func_id to a crate level map with the noir function and the module id // Encountering a NoirFunction, we retrieve it's module_data to get the namespace @@ -266,7 +272,9 @@ impl<'a> ModCollector<'a> { // Create the corresponding module for the struct namespace let id = match self.push_child_module(&name, self.file_id, false, false) { - Ok(local_id) => context.def_interner.new_struct(&unresolved, krate, local_id), + Ok(local_id) => { + context.def_interner.new_struct(&unresolved, krate, local_id, self.file_id) + } Err(error) => { definition_errors.push((error.into(), self.file_id)); continue; @@ -343,7 +351,7 @@ impl<'a> ModCollector<'a> { let name = trait_definition.name.clone(); // Create the corresponding module for the trait namespace - let id = match self.push_child_module(&name, self.file_id, false, false) { + let trait_id = match self.push_child_module(&name, self.file_id, false, false) { Ok(local_id) => TraitId(ModuleId { krate, local_id }), Err(error) => { errors.push((error.into(), self.file_id)); @@ -353,7 +361,7 @@ impl<'a> ModCollector<'a> { // Add the trait to scope so its path can be looked up later let result = - self.def_collector.def_map.modules[self.module_id.0].declare_trait(name, id); + self.def_collector.def_map.modules[self.module_id.0].declare_trait(name, trait_id); if let Err((first_def, second_def)) = result { let error = DefCollectorErrorKind::Duplicate { @@ -370,6 +378,8 @@ impl<'a> ModCollector<'a> { functions: Vec::new(), trait_id: None, }; + + let mut method_ids = HashMap::new(); for trait_item in &trait_definition.items { match trait_item { TraitItem::Function { @@ -381,6 +391,8 @@ impl<'a> ModCollector<'a> { body, } => { let func_id = context.def_interner.push_empty_fn(); + method_ids.insert(name.to_string(), func_id); + let modifiers = FunctionModifiers { name: name.to_string(), visibility: crate::FunctionVisibility::Public, @@ -391,9 +403,12 @@ impl<'a> ModCollector<'a> { is_internal: None, }; - context.def_interner.push_function_definition(func_id, modifiers, id.0); + let location = Location::new(name.span(), self.file_id); + context + .def_interner + .push_function_definition(func_id, modifiers, trait_id.0, location); - match self.def_collector.def_map.modules[id.0.local_id.0] + match self.def_collector.def_map.modules[trait_id.0.local_id.0] .declare_function(name.clone(), func_id) { Ok(()) => { @@ -428,7 +443,7 @@ impl<'a> ModCollector<'a> { let stmt_id = context.def_interner.push_empty_global(); if let Err((first_def, second_def)) = self.def_collector.def_map.modules - [id.0.local_id.0] + [trait_id.0.local_id.0] .declare_global(name.clone(), stmt_id) { let error = DefCollectorErrorKind::Duplicate { @@ -442,7 +457,7 @@ impl<'a> ModCollector<'a> { TraitItem::Type { name } => { // TODO(nickysn or alexvitkov): implement context.def_interner.push_empty_type_alias and get an id, instead of using TypeAliasId::dummy_id() if let Err((first_def, second_def)) = self.def_collector.def_map.modules - [id.0.local_id.0] + [trait_id.0.local_id.0] .declare_type_alias(name.clone(), TypeAliasId::dummy_id()) { let error = DefCollectorErrorKind::Duplicate { @@ -462,9 +477,10 @@ impl<'a> ModCollector<'a> { module_id: self.module_id, crate_id: krate, trait_def: trait_definition, + method_ids, fns_with_default_impl: unresolved_functions, }; - self.def_collector.collected_traits.insert(id, unresolved); + self.def_collector.collected_traits.insert(trait_id, unresolved); } errors } @@ -528,11 +544,11 @@ impl<'a> ModCollector<'a> { }; errors.push((error.into(), location.file)); - let error2 = DefCollectorErrorKind::ModuleOriginallyDefined { + let error = DefCollectorErrorKind::ModuleOriginallyDefined { mod_name: mod_name.clone(), span: old_location.span, }; - errors.push((error2.into(), old_location.file)); + errors.push((error.into(), old_location.file)); return errors; } diff --git a/compiler/noirc_frontend/src/hir/def_collector/errors.rs b/compiler/noirc_frontend/src/hir/def_collector/errors.rs index edb39fe68d..2b91c4b36c 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/errors.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/errors.rs @@ -73,15 +73,16 @@ pub enum DefCollectorErrorKind { "Either the type or the trait must be from the same crate as the trait implementation" )] TraitImplOrphaned { span: Span }, + #[error("macro error : {0:?}")] + MacroError(MacroError), +} - // Aztec feature flag errors - // TODO(benesjan): https://github.com/AztecProtocol/aztec-packages/issues/2905 - #[cfg(feature = "aztec")] - #[error("Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml")] - AztecNotFound {}, - #[cfg(feature = "aztec")] - #[error("compute_note_hash_and_nullifier function not found. Define it in your contract.")] - AztecComputeNoteHashAndNullifierNotFound { span: Span }, +/// An error struct that macro processors can return. +#[derive(Debug, Clone)] +pub struct MacroError { + pub primary_message: String, + pub secondary_message: Option, + pub span: Option, } impl DefCollectorErrorKind { @@ -245,16 +246,9 @@ impl From for Diagnostic { "Either the type or the trait must be from the same crate as the trait implementation".into(), span, ), - #[cfg(feature = "aztec")] - DefCollectorErrorKind::AztecNotFound {} => Diagnostic::from_message( - "Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml", - ), - #[cfg(feature = "aztec")] - DefCollectorErrorKind::AztecComputeNoteHashAndNullifierNotFound {span} => Diagnostic::simple_error( - "compute_note_hash_and_nullifier function not found. Define it in your contract.".into(), - "".into(), - span - ), + DefCollectorErrorKind::MacroError(macro_error) => { + Diagnostic::simple_error(macro_error.primary_message, macro_error.secondary_message.unwrap_or_default(), macro_error.span.unwrap_or_default()) + }, } } } diff --git a/compiler/noirc_frontend/src/hir/def_map/item_scope.rs b/compiler/noirc_frontend/src/hir/def_map/item_scope.rs index 42cca55065..523def8951 100644 --- a/compiler/noirc_frontend/src/hir/def_map/item_scope.rs +++ b/compiler/noirc_frontend/src/hir/def_map/item_scope.rs @@ -5,6 +5,8 @@ use crate::{ }; use std::collections::{hash_map::Entry, HashMap}; +type Scope = HashMap, (ModuleDefId, Visibility, bool /*is_prelude*/)>; + #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum Visibility { Public, @@ -12,8 +14,8 @@ pub enum Visibility { #[derive(Default, Debug, PartialEq, Eq)] pub struct ItemScope { - types: HashMap, (ModuleDefId, Visibility)>>, - values: HashMap, (ModuleDefId, Visibility)>>, + types: HashMap, + values: HashMap, defs: Vec, } @@ -25,7 +27,7 @@ impl ItemScope { mod_def: ModuleDefId, trait_id: Option, ) -> Result<(), (Ident, Ident)> { - self.add_item_to_namespace(name, mod_def, trait_id)?; + self.add_item_to_namespace(name, mod_def, trait_id, false)?; self.defs.push(mod_def); Ok(()) } @@ -38,25 +40,31 @@ impl ItemScope { name: Ident, mod_def: ModuleDefId, trait_id: Option, + is_prelude: bool, ) -> Result<(), (Ident, Ident)> { - let add_item = - |map: &mut HashMap, (ModuleDefId, Visibility)>>| { - if let Entry::Occupied(mut o) = map.entry(name.clone()) { - let trait_hashmap = o.get_mut(); - if let Entry::Occupied(_) = trait_hashmap.entry(trait_id) { - let old_ident = o.key(); - Err((old_ident.clone(), name)) - } else { - trait_hashmap.insert(trait_id, (mod_def, Visibility::Public)); + let add_item = |map: &mut HashMap| { + if let Entry::Occupied(mut o) = map.entry(name.clone()) { + let trait_hashmap = o.get_mut(); + if let Entry::Occupied(mut n) = trait_hashmap.entry(trait_id) { + let is_prelude = std::mem::replace(&mut n.get_mut().2, is_prelude); + let old_ident = o.key(); + + if is_prelude { Ok(()) + } else { + Err((old_ident.clone(), name)) } } else { - let mut trait_hashmap = HashMap::new(); - trait_hashmap.insert(trait_id, (mod_def, Visibility::Public)); - map.insert(name, trait_hashmap); + trait_hashmap.insert(trait_id, (mod_def, Visibility::Public, is_prelude)); Ok(()) } - }; + } else { + let mut trait_hashmap = HashMap::new(); + trait_hashmap.insert(trait_id, (mod_def, Visibility::Public, is_prelude)); + map.insert(name, trait_hashmap); + Ok(()) + } + }; match mod_def { ModuleDefId::ModuleId(_) => add_item(&mut self.types), @@ -69,7 +77,7 @@ impl ItemScope { } pub fn find_module_with_name(&self, mod_name: &Ident) -> Option<&ModuleId> { - let (module_def, _) = self.types.get(mod_name)?.get(&None)?; + let (module_def, _, _) = self.types.get(mod_name)?.get(&None)?; match module_def { ModuleDefId::ModuleId(id) => Some(id), _ => None, @@ -81,13 +89,13 @@ impl ItemScope { // methods introduced without trait take priority and hide methods with the same name that come from a trait let a = trait_hashmap.get(&None); match a { - Some((module_def, _)) => match module_def { + Some((module_def, _, _)) => match module_def { ModuleDefId::FunctionId(id) => Some(*id), _ => None, }, None => { if trait_hashmap.len() == 1 { - let (module_def, _) = trait_hashmap.get(trait_hashmap.keys().last()?)?; + let (module_def, _, _) = trait_hashmap.get(trait_hashmap.keys().last()?)?; match module_def { ModuleDefId::FunctionId(id) => Some(*id), _ => None, @@ -105,7 +113,7 @@ impl ItemScope { func_name: &Ident, trait_id: &Option, ) -> Option { - let (module_def, _) = self.values.get(func_name)?.get(trait_id)?; + let (module_def, _, _) = self.values.get(func_name)?.get(trait_id)?; match module_def { ModuleDefId::FunctionId(id) => Some(*id), _ => None, @@ -115,20 +123,19 @@ impl ItemScope { pub fn find_name(&self, name: &Ident) -> PerNs { // Names, not associated with traits are searched first. If not found, we search for name, coming from a trait. // If we find only one name from trait, we return it. If there are multiple traits, providing the same name, we return None. - let find_name_in = - |a: &HashMap, (ModuleDefId, Visibility)>>| { - if let Some(t) = a.get(name) { - if let Some(tt) = t.get(&None) { - Some(*tt) - } else if t.len() == 1 { - t.values().last().cloned() - } else { - None - } + let find_name_in = |a: &HashMap| { + if let Some(t) = a.get(name) { + if let Some(tt) = t.get(&None) { + Some(*tt) + } else if t.len() == 1 { + t.values().last().cloned() } else { None } - }; + } else { + None + } + }; PerNs { types: find_name_in(&self.types), values: find_name_in(&self.values) } } @@ -144,15 +151,19 @@ impl ItemScope { } } + pub fn names(&self) -> impl Iterator { + self.types.keys().chain(self.values.keys()) + } + pub fn definitions(&self) -> Vec { self.defs.clone() } - pub fn types(&self) -> &HashMap, (ModuleDefId, Visibility)>> { + pub fn types(&self) -> &HashMap { &self.types } - pub fn values(&self) -> &HashMap, (ModuleDefId, Visibility)>> { + pub fn values(&self) -> &HashMap { &self.values } diff --git a/compiler/noirc_frontend/src/hir/def_map/mod.rs b/compiler/noirc_frontend/src/hir/def_map/mod.rs index 345e5447bf..026f407981 100644 --- a/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -1,6 +1,7 @@ use crate::graph::CrateId; use crate::hir::def_collector::dc_crate::{CompilationError, DefCollector}; use crate::hir::Context; +use crate::macros_api::MacroProcessor; use crate::node_interner::{FuncId, NodeInterner, StructId}; use crate::parser::{parse_program, ParsedModule, ParserError}; use crate::token::{FunctionAttribute, SecondaryAttribute, TestScope}; @@ -17,6 +18,8 @@ pub use module_data::*; mod namespace; pub use namespace::*; +use super::def_collector::errors::DefCollectorErrorKind; + /// The name that is used for a non-contract program's entry-point function. pub const MAIN_FUNCTION: &str = "main"; @@ -69,6 +72,7 @@ impl CrateDefMap { pub fn collect_defs( crate_id: CrateId, context: &mut Context, + macro_processors: Vec<&dyn MacroProcessor>, ) -> Vec<(CompilationError, FileId)> { // Check if this Crate has already been compiled // XXX: There is probably a better alternative for this. @@ -83,16 +87,18 @@ impl CrateDefMap { // First parse the root file. let root_file_id = context.crate_graph[crate_id].root_file_id; let (ast, parsing_errors) = parse_file(&context.file_manager, root_file_id); - let ast = ast.into_sorted(); - - #[cfg(feature = "aztec")] - let ast = match super::aztec_library::transform(ast, &crate_id, context) { - Ok(ast) => ast, - Err((error, file_id)) => { - errors.push((error.into(), file_id)); - return errors; - } - }; + let mut ast = ast.into_sorted(); + + for macro_processor in ¯o_processors { + ast = match macro_processor.process_untyped_ast(ast, &crate_id, context) { + Ok(ast) => ast, + Err((error, file_id)) => { + let def_error = DefCollectorErrorKind::MacroError(error); + errors.push((def_error.into(), file_id)); + return errors; + } + }; + } // Allocate a default Module for the root, giving it a ModuleId let mut modules: Arena = Arena::default(); @@ -107,7 +113,13 @@ impl CrateDefMap { }; // Now we want to populate the CrateDefMap using the DefCollector - errors.extend(DefCollector::collect(def_map, context, ast, root_file_id)); + errors.extend(DefCollector::collect( + def_map, + context, + ast, + root_file_id, + macro_processors.clone(), + )); errors.extend( parsing_errors.iter().map(|e| (e.clone().into(), root_file_id)).collect::>(), @@ -161,7 +173,6 @@ impl CrateDefMap { }) }) } - /// Go through all modules in this crate, find all `contract ... { ... }` declarations, /// and collect them all into a Vec. pub fn get_all_contracts(&self, interner: &NodeInterner) -> Vec { diff --git a/compiler/noirc_frontend/src/hir/def_map/module_data.rs b/compiler/noirc_frontend/src/hir/def_map/module_data.rs index 29b11e92c0..fbb5e5cf74 100644 --- a/compiler/noirc_frontend/src/hir/def_map/module_data.rs +++ b/compiler/noirc_frontend/src/hir/def_map/module_data.rs @@ -41,6 +41,10 @@ impl ModuleData { } } + pub(crate) fn scope(&self) -> &ItemScope { + &self.scope + } + fn declare( &mut self, name: Ident, @@ -104,8 +108,13 @@ impl ModuleData { self.scope.find_func_with_name(name) } - pub fn import(&mut self, name: Ident, id: ModuleDefId) -> Result<(), (Ident, Ident)> { - self.scope.add_item_to_namespace(name, id, None) + pub fn import( + &mut self, + name: Ident, + id: ModuleDefId, + is_prelude: bool, + ) -> Result<(), (Ident, Ident)> { + self.scope.add_item_to_namespace(name, id, None, is_prelude) } pub fn find_name(&self, name: &Ident) -> PerNs { @@ -113,12 +122,12 @@ impl ModuleData { } pub fn type_definitions(&self) -> impl Iterator + '_ { - self.definitions.types().values().flat_map(|a| a.values().map(|(id, _)| *id)) + self.definitions.types().values().flat_map(|a| a.values().map(|(id, _, _)| *id)) } /// Return an iterator over all definitions defined within this module, /// excluding any type definitions. pub fn value_definitions(&self) -> impl Iterator + '_ { - self.definitions.values().values().flat_map(|a| a.values().map(|(id, _)| *id)) + self.definitions.values().values().flat_map(|a| a.values().map(|(id, _, _)| *id)) } } diff --git a/compiler/noirc_frontend/src/hir/def_map/module_def.rs b/compiler/noirc_frontend/src/hir/def_map/module_def.rs index 659d7712ab..3e5629639f 100644 --- a/compiler/noirc_frontend/src/hir/def_map/module_def.rs +++ b/compiler/noirc_frontend/src/hir/def_map/module_def.rs @@ -61,6 +61,13 @@ impl ModuleDefId { ModuleDefId::GlobalId(_) => "global", } } + + pub fn as_module(&self) -> Option { + match self { + Self::ModuleId(v) => Some(*v), + _ => None, + } + } } impl From for ModuleDefId { diff --git a/compiler/noirc_frontend/src/hir/def_map/namespace.rs b/compiler/noirc_frontend/src/hir/def_map/namespace.rs index 9221b389d8..ca14d9f861 100644 --- a/compiler/noirc_frontend/src/hir/def_map/namespace.rs +++ b/compiler/noirc_frontend/src/hir/def_map/namespace.rs @@ -3,13 +3,13 @@ use super::{item_scope::Visibility, ModuleDefId}; // This works exactly the same as in r-a, just simplified #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct PerNs { - pub types: Option<(ModuleDefId, Visibility)>, - pub values: Option<(ModuleDefId, Visibility)>, + pub types: Option<(ModuleDefId, Visibility, bool)>, + pub values: Option<(ModuleDefId, Visibility, bool)>, } impl PerNs { pub fn types(t: ModuleDefId) -> PerNs { - PerNs { types: Some((t, Visibility::Public)), values: None } + PerNs { types: Some((t, Visibility::Public, false)), values: None } } pub fn take_types(self) -> Option { @@ -24,7 +24,7 @@ impl PerNs { self.types.map(|it| it.0).into_iter().chain(self.values.map(|it| it.0)) } - pub fn iter_items(self) -> impl Iterator { + pub fn iter_items(self) -> impl Iterator { self.types.into_iter().chain(self.values) } diff --git a/compiler/noirc_frontend/src/hir/mod.rs b/compiler/noirc_frontend/src/hir/mod.rs index 5a28d7b779..3a435f302a 100644 --- a/compiler/noirc_frontend/src/hir/mod.rs +++ b/compiler/noirc_frontend/src/hir/mod.rs @@ -4,9 +4,6 @@ pub mod resolution; pub mod scope; pub mod type_check; -#[cfg(feature = "aztec")] -pub(crate) mod aztec_library; - use crate::graph::{CrateGraph, CrateId}; use crate::hir_def::function::FuncMeta; use crate::node_interner::{FuncId, NodeInterner, StructId}; @@ -29,10 +26,6 @@ pub struct Context { /// A map of each file that already has been visited from a prior `mod foo;` declaration. /// This is used to issue an error if a second `mod foo;` is declared to the same file. pub visited_files: BTreeMap, - - /// Maps a given (contract) module id to the next available storage slot - /// for that contract. - pub storage_slots: BTreeMap, } #[derive(Debug, Copy, Clone)] @@ -42,8 +35,6 @@ pub enum FunctionNameMatch<'a> { Contains(&'a str), } -pub type StorageSlot = u32; - impl Context { pub fn new(file_manager: FileManager, crate_graph: CrateGraph) -> Context { Context { @@ -52,7 +43,6 @@ impl Context { visited_files: BTreeMap::new(), crate_graph, file_manager, - storage_slots: BTreeMap::new(), } } @@ -190,6 +180,14 @@ impl Context { .collect() } + /// Returns the [Location] of the definition of the given Ident found at [Span] of the given [FileId]. + /// Returns [None] when definition is not found. + pub fn get_definition_location_from(&self, location: Location) -> Option { + let interner = &self.def_interner; + + interner.find_location_index(location).and_then(|index| interner.resolve_location(index)) + } + /// Return a Vec of all `contract` declarations in the source code and the functions they contain pub fn get_all_contracts(&self, crate_id: &CrateId) -> Vec { self.def_map(crate_id) @@ -200,16 +198,4 @@ impl Context { fn module(&self, module_id: def_map::ModuleId) -> &def_map::ModuleData { module_id.module(&self.def_maps) } - - /// Returns the next available storage slot in the given module. - /// Returns None if the given module is not a contract module. - fn next_storage_slot(&mut self, module_id: def_map::ModuleId) -> Option { - let module = self.module(module_id); - - module.is_contract.then(|| { - let next_slot = self.storage_slots.entry(module_id).or_insert(0); - *next_slot += 1; - *next_slot - }) - } } diff --git a/compiler/noirc_frontend/src/hir/resolution/functions.rs b/compiler/noirc_frontend/src/hir/resolution/functions.rs new file mode 100644 index 0000000000..e63de9b917 --- /dev/null +++ b/compiler/noirc_frontend/src/hir/resolution/functions.rs @@ -0,0 +1,85 @@ +use std::{collections::BTreeMap, rc::Rc}; + +use fm::FileId; +use iter_extended::vecmap; +use noirc_errors::Span; + +use crate::{ + graph::CrateId, + hir::{ + def_collector::dc_crate::{CompilationError, UnresolvedFunctions}, + def_map::{CrateDefMap, ModuleId}, + }, + node_interner::{FuncId, NodeInterner, TraitImplId}, + Type, TypeVariable, +}; + +use super::{path_resolver::StandardPathResolver, resolver::Resolver}; + +#[allow(clippy::too_many_arguments)] +pub(crate) fn resolve_function_set( + interner: &mut NodeInterner, + crate_id: CrateId, + def_maps: &BTreeMap, + mut unresolved_functions: UnresolvedFunctions, + self_type: Option, + trait_impl_id: Option, + impl_generics: Vec<(Rc, TypeVariable, Span)>, + errors: &mut Vec<(CompilationError, FileId)>, +) -> Vec<(FileId, FuncId)> { + let file_id = unresolved_functions.file_id; + + let where_clause_errors = + unresolved_functions.resolve_trait_bounds_trait_ids(def_maps, crate_id); + errors.extend(where_clause_errors.iter().cloned().map(|e| (e.into(), file_id))); + + vecmap(unresolved_functions.functions, |(mod_id, func_id, func)| { + let module_id = ModuleId { krate: crate_id, local_id: mod_id }; + let path_resolver = StandardPathResolver::new(module_id); + + let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file_id); + // Must use set_generics here to ensure we re-use the same generics from when + // the impl was originally collected. Otherwise the function will be using different + // TypeVariables for the same generic, causing it to instantiate incorrectly. + resolver.set_generics(impl_generics.clone()); + resolver.set_self_type(self_type.clone()); + resolver.set_trait_id(unresolved_functions.trait_id); + resolver.set_trait_impl_id(trait_impl_id); + + // Without this, impl methods can accidentally be placed in contracts. See #3254 + if self_type.is_some() { + resolver.set_in_contract(false); + } + + let (hir_func, func_meta, errs) = resolver.resolve_function(func, func_id); + interner.push_fn_meta(func_meta, func_id); + interner.update_fn(func_id, hir_func); + errors.extend(errs.iter().cloned().map(|e| (e.into(), file_id))); + (file_id, func_id) + }) +} + +pub(crate) fn resolve_free_functions( + interner: &mut NodeInterner, + crate_id: CrateId, + def_maps: &BTreeMap, + collected_functions: Vec, + self_type: Option, + errors: &mut Vec<(CompilationError, FileId)>, +) -> Vec<(FileId, FuncId)> { + collected_functions + .into_iter() + .flat_map(|unresolved_functions| { + resolve_function_set( + interner, + crate_id, + def_maps, + unresolved_functions, + self_type.clone(), + None, + vec![], // no impl generics + errors, + ) + }) + .collect() +} diff --git a/compiler/noirc_frontend/src/hir/resolution/globals.rs b/compiler/noirc_frontend/src/hir/resolution/globals.rs new file mode 100644 index 0000000000..b5aec212db --- /dev/null +++ b/compiler/noirc_frontend/src/hir/resolution/globals.rs @@ -0,0 +1,55 @@ +use super::{path_resolver::StandardPathResolver, resolver::Resolver, take_errors}; +use crate::{ + graph::CrateId, + hir::{ + def_collector::dc_crate::{CompilationError, UnresolvedGlobal}, + def_map::ModuleId, + Context, + }, + node_interner::StmtId, +}; +use fm::FileId; +use iter_extended::vecmap; + +pub(crate) struct ResolvedGlobals { + pub(crate) globals: Vec<(FileId, StmtId)>, + pub(crate) errors: Vec<(CompilationError, FileId)>, +} + +impl ResolvedGlobals { + pub(crate) fn extend(&mut self, oth: Self) { + self.globals.extend(oth.globals); + self.errors.extend(oth.errors); + } +} + +pub(crate) fn resolve_globals( + context: &mut Context, + globals: Vec, + crate_id: CrateId, +) -> ResolvedGlobals { + let mut errors: Vec<(CompilationError, FileId)> = vec![]; + let globals = vecmap(globals, |global| { + let module_id = ModuleId { local_id: global.module_id, krate: crate_id }; + let path_resolver = StandardPathResolver::new(module_id); + + let mut resolver = Resolver::new( + &mut context.def_interner, + &path_resolver, + &context.def_maps, + global.file_id, + ); + + let name = global.stmt_def.pattern.name_ident().clone(); + + let hir_stmt = resolver.resolve_global_let(global.stmt_def); + errors.extend(take_errors(global.file_id, resolver)); + + context.def_interner.update_global(global.stmt_id, hir_stmt); + + context.def_interner.push_global(global.stmt_id, name, global.module_id); + + (global.file_id, global.stmt_id) + }); + ResolvedGlobals { globals, errors } +} diff --git a/compiler/noirc_frontend/src/hir/resolution/impls.rs b/compiler/noirc_frontend/src/hir/resolution/impls.rs new file mode 100644 index 0000000000..4aa70f00cf --- /dev/null +++ b/compiler/noirc_frontend/src/hir/resolution/impls.rs @@ -0,0 +1,137 @@ +use std::collections::BTreeMap; + +use fm::FileId; + +use crate::{ + graph::CrateId, + hir::{ + def_collector::{ + dc_crate::{CompilationError, ImplMap}, + errors::DefCollectorErrorKind, + }, + def_map::{CrateDefMap, ModuleId}, + Context, + }, + node_interner::{FuncId, NodeInterner}, + Type, +}; + +use super::{ + errors::ResolverError, functions, get_module_mut, get_struct_type, + path_resolver::StandardPathResolver, resolver::Resolver, take_errors, +}; + +/// Go through the list of impls and add each function within to the scope +/// of the module defined by its type. +pub(crate) fn collect_impls( + context: &mut Context, + crate_id: CrateId, + collected_impls: &ImplMap, +) -> Vec<(CompilationError, FileId)> { + let interner = &mut context.def_interner; + let def_maps = &mut context.def_maps; + let mut errors: Vec<(CompilationError, FileId)> = vec![]; + + for ((unresolved_type, module_id), methods) in collected_impls { + let path_resolver = + StandardPathResolver::new(ModuleId { local_id: *module_id, krate: crate_id }); + + let file = def_maps[&crate_id].file_id(*module_id); + + for (generics, span, unresolved) in methods { + let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); + resolver.add_generics(generics); + let typ = resolver.resolve_type(unresolved_type.clone()); + + errors.extend(take_errors(unresolved.file_id, resolver)); + + if let Some(struct_type) = get_struct_type(&typ) { + let struct_type = struct_type.borrow(); + + // `impl`s are only allowed on types defined within the current crate + if struct_type.id.krate() != crate_id { + let span = *span; + let type_name = struct_type.name.to_string(); + let error = DefCollectorErrorKind::ForeignImpl { span, type_name }; + errors.push((error.into(), unresolved.file_id)); + continue; + } + + // Grab the module defined by the struct type. Note that impls are a case + // where the module the methods are added to is not the same as the module + // they are resolved in. + let module = get_module_mut(def_maps, struct_type.id.module_id()); + + for (_, method_id, method) in &unresolved.functions { + // If this method was already declared, remove it from the module so it cannot + // be accessed with the `TypeName::method` syntax. We'll check later whether the + // object types in each method overlap or not. If they do, we issue an error. + // If not, that is specialization which is allowed. + if module.declare_function(method.name_ident().clone(), *method_id).is_err() { + module.remove_function(method.name_ident()); + } + } + // Prohibit defining impls for primitive types if we're not in the stdlib + } else if typ != Type::Error && !crate_id.is_stdlib() { + let span = *span; + let error = DefCollectorErrorKind::NonStructTypeInImpl { span }; + errors.push((error.into(), unresolved.file_id)); + } + } + } + errors +} + +pub(crate) fn resolve_impls( + interner: &mut NodeInterner, + crate_id: CrateId, + def_maps: &BTreeMap, + collected_impls: ImplMap, + errors: &mut Vec<(CompilationError, FileId)>, +) -> Vec<(FileId, FuncId)> { + let mut file_method_ids = Vec::new(); + + for ((unresolved_type, module_id), methods) in collected_impls { + let path_resolver = + StandardPathResolver::new(ModuleId { local_id: module_id, krate: crate_id }); + + let file = def_maps[&crate_id].file_id(module_id); + + for (generics, _, functions) in methods { + let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); + resolver.add_generics(&generics); + let generics = resolver.get_generics().to_vec(); + let self_type = resolver.resolve_type(unresolved_type.clone()); + + let mut file_func_ids = functions::resolve_function_set( + interner, + crate_id, + def_maps, + functions, + Some(self_type.clone()), + None, + generics, + errors, + ); + if self_type != Type::Error { + for (file_id, method_id) in &file_func_ids { + let method_name = interner.function_name(method_id).to_owned(); + + if let Some(first_fn) = + interner.add_method(&self_type, method_name.clone(), *method_id, false) + { + let error = ResolverError::DuplicateDefinition { + name: method_name, + first_span: interner.function_ident(&first_fn).span(), + second_span: interner.function_ident(method_id).span(), + }; + errors.push((error.into(), *file_id)); + } + } + } + file_method_ids.append(&mut file_func_ids); + } + } + + file_method_ids +} diff --git a/compiler/noirc_frontend/src/hir/resolution/import.rs b/compiler/noirc_frontend/src/hir/resolution/import.rs index 6f3140a65d..41fdac746b 100644 --- a/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -1,5 +1,5 @@ use iter_extended::partition_results; -use noirc_errors::CustomDiagnostic; +use noirc_errors::{CustomDiagnostic, Span}; use crate::graph::CrateId; use std::collections::BTreeMap; @@ -12,6 +12,7 @@ pub struct ImportDirective { pub module_id: LocalModuleId, pub path: Path, pub alias: Option, + pub is_prelude: bool, } pub type PathResolution = Result; @@ -30,6 +31,7 @@ pub struct ResolvedImport { pub resolved_namespace: PerNs, // The module which we must add the resolved namespace to pub module_scope: LocalModuleId, + pub is_prelude: bool, } impl From for CustomDiagnostic { @@ -66,7 +68,12 @@ pub fn resolve_imports( .map_err(|error| (error, module_scope))?; let name = resolve_path_name(&import_directive); - Ok(ResolvedImport { name, resolved_namespace, module_scope }) + Ok(ResolvedImport { + name, + resolved_namespace, + module_scope, + is_prelude: import_directive.is_prelude, + }) }) } @@ -202,9 +209,17 @@ fn resolve_external_dep( // Create an import directive for the dependency crate let path_without_crate_name = &path[1..]; // XXX: This will panic if the path is of the form `use dep::std` Ideal algorithm will not distinguish between crate and module - let path = Path { segments: path_without_crate_name.to_vec(), kind: PathKind::Plain }; - let dep_directive = - ImportDirective { module_id: dep_module.local_id, path, alias: directive.alias.clone() }; + let path = Path { + segments: path_without_crate_name.to_vec(), + kind: PathKind::Plain, + span: Span::default(), + }; + let dep_directive = ImportDirective { + module_id: dep_module.local_id, + path, + alias: directive.alias.clone(), + is_prelude: false, + }; let dep_def_map = def_maps.get(&dep_module.krate).unwrap(); diff --git a/compiler/noirc_frontend/src/hir/resolution/mod.rs b/compiler/noirc_frontend/src/hir/resolution/mod.rs index 601e78015c..8c16a9cca8 100644 --- a/compiler/noirc_frontend/src/hir/resolution/mod.rs +++ b/compiler/noirc_frontend/src/hir/resolution/mod.rs @@ -9,3 +9,50 @@ pub mod errors; pub mod import; pub mod path_resolver; pub mod resolver; + +mod functions; +mod globals; +mod impls; +mod structs; +mod traits; +mod type_aliases; + +pub(crate) use functions::resolve_free_functions; +pub(crate) use globals::resolve_globals; +pub(crate) use impls::{collect_impls, resolve_impls}; +pub(crate) use structs::resolve_structs; +pub(crate) use traits::{ + collect_trait_impls, resolve_trait_by_path, resolve_trait_impls, resolve_traits, +}; +pub(crate) use type_aliases::resolve_type_aliases; + +use crate::{ + graph::CrateId, + hir::{ + def_collector::dc_crate::CompilationError, + def_map::{CrateDefMap, ModuleData, ModuleId}, + }, + Shared, StructType, Type, +}; +use fm::FileId; +use iter_extended::vecmap; +use resolver::Resolver; +use std::collections::BTreeMap; + +fn take_errors(file_id: FileId, resolver: Resolver<'_>) -> Vec<(CompilationError, FileId)> { + vecmap(resolver.take_errors(), |e| (e.into(), file_id)) +} + +fn get_module_mut( + def_maps: &mut BTreeMap, + module: ModuleId, +) -> &mut ModuleData { + &mut def_maps.get_mut(&module.krate).unwrap().modules[module.local_id.0] +} + +fn get_struct_type(typ: &Type) -> Option<&Shared> { + match typ { + Type::Struct(definition, _) => Some(definition), + _ => None, + } +} diff --git a/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs b/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs index 4c16edd56f..4c5fa3bcee 100644 --- a/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/path_resolver.rs @@ -57,14 +57,15 @@ pub fn resolve_path( path: Path, ) -> Result { // lets package up the path into an ImportDirective and resolve it using that - let import = ImportDirective { module_id: module_id.local_id, path, alias: None }; + let import = + ImportDirective { module_id: module_id.local_id, path, alias: None, is_prelude: false }; let allow_referencing_contracts = allow_referencing_contracts(def_maps, module_id.krate, module_id.local_id); let def_map = &def_maps[&module_id.krate]; let ns = resolve_path_to_ns(&import, def_map, def_maps, allow_referencing_contracts)?; - let function = ns.values.map(|(id, _)| id); - let id = function.or_else(|| ns.types.map(|(id, _)| id)); + let function = ns.values.map(|(id, _, _)| id); + let id = function.or_else(|| ns.types.map(|(id, _, _)| id)); Ok(id.expect("Found empty namespace")) } diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 4b829932b7..9cd28d8078 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -19,7 +19,7 @@ use crate::hir_def::expr::{ }; use crate::hir_def::traits::{Trait, TraitConstraint}; -use crate::token::FunctionAttribute; +use crate::token::{Attributes, FunctionAttribute}; use regex::Regex; use std::collections::{BTreeMap, HashSet}; use std::rc::Rc; @@ -37,11 +37,11 @@ use crate::{ StatementKind, }; use crate::{ - ArrayLiteral, ContractFunctionType, Distinctness, ForRange, FunctionVisibility, Generics, - LValue, NoirStruct, NoirTypeAlias, Param, Path, PathKind, Pattern, Shared, StructType, Type, - TypeAliasType, TypeBinding, TypeVariable, UnaryOp, UnresolvedGenerics, - UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, - Visibility, ERROR_IDENT, + ArrayLiteral, ContractFunctionType, Distinctness, ForRange, FunctionDefinition, + FunctionReturnType, FunctionVisibility, Generics, LValue, NoirStruct, NoirTypeAlias, Param, + Path, PathKind, Pattern, Shared, StructType, Type, TypeAliasType, TypeBinding, TypeVariable, + UnaryOp, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, + UnresolvedTypeExpression, Visibility, ERROR_IDENT, }; use fm::FileId; use iter_extended::vecmap; @@ -200,6 +200,51 @@ impl<'a> Resolver<'a> { (hir_func, func_meta, self.errors) } + pub fn resolve_trait_function( + &mut self, + name: &Ident, + parameters: &[(Ident, UnresolvedType)], + return_type: &FunctionReturnType, + where_clause: &[UnresolvedTraitConstraint], + func_id: FuncId, + ) -> (HirFunction, FuncMeta) { + self.scopes.start_function(); + + // Check whether the function has globals in the local module and add them to the scope + self.resolve_local_globals(); + + self.trait_bounds = where_clause.to_vec(); + + let kind = FunctionKind::Normal; + let def = FunctionDefinition { + name: name.clone(), + attributes: Attributes::empty(), + is_open: false, + is_internal: false, + is_unconstrained: false, + visibility: FunctionVisibility::Public, // Trait functions are always public + generics: Vec::new(), // self.generics should already be set + parameters: vecmap(parameters, |(name, typ)| Param { + visibility: Visibility::Private, + pattern: Pattern::Identifier(name.clone()), + typ: typ.clone(), + span: name.span(), + }), + body: BlockExpression(Vec::new()), + span: name.span(), + where_clause: where_clause.to_vec(), + return_type: return_type.clone(), + return_visibility: Visibility::Private, + return_distinctness: Distinctness::DuplicationAllowed, + }; + + let (hir_func, func_meta) = self.intern_function(NoirFunction { kind, def }, func_id); + let _ = self.scopes.end_function(); + // Don't check the scope tree for unused variables, they can't be used in a declaration anyway. + self.trait_bounds.clear(); + (hir_func, func_meta) + } + fn check_for_unused_variables_in_scope_tree(&mut self, scope_decls: ScopeTree) { let mut unused_vars = Vec::new(); for scope in scope_decls.0.into_iter() { @@ -256,8 +301,9 @@ impl<'a> Resolver<'a> { return self.add_global_variable_decl(name, definition); } - let id = self.interner.push_definition(name.0.contents.clone(), mutable, definition); let location = Location::new(name.span(), self.file); + let id = + self.interner.push_definition(name.0.contents.clone(), mutable, definition, location); let ident = HirIdent { location, id }; let resolver_meta = ResolverMeta { num_times_used: 0, ident, warn_if_unused }; @@ -300,8 +346,9 @@ impl<'a> Resolver<'a> { ident = hir_let_stmt.ident(); resolver_meta = ResolverMeta { num_times_used: 0, ident, warn_if_unused: true }; } else { - let id = self.interner.push_definition(name.0.contents.clone(), false, definition); let location = Location::new(name.span(), self.file); + let id = + self.interner.push_definition(name.0.contents.clone(), false, definition, location); ident = HirIdent { location, id }; resolver_meta = ResolverMeta { num_times_used: 0, ident, warn_if_unused: true }; } @@ -441,6 +488,7 @@ impl<'a> Resolver<'a> { MutableReference(element) => { Type::MutableReference(Box::new(self.resolve_type_inner(*element, new_variables))) } + Parenthesized(typ) => self.resolve_type_inner(*typ, new_variables), } } @@ -520,7 +568,7 @@ impl<'a> Resolver<'a> { _new_variables: &mut Generics, ) -> Type { if let Some(t) = self.lookup_trait_or_error(path) { - Type::TraitAsType(t) + Type::TraitAsType(t.id, Rc::new(t.name.to_string())) } else { Type::Error } @@ -571,7 +619,7 @@ impl<'a> Resolver<'a> { match length { None => { let id = self.interner.next_type_variable_id(); - let typevar = Shared::new(TypeBinding::Unbound(id)); + let typevar = TypeVariable::unbound(id); new_variables.push((id, typevar.clone())); // 'Named'Generic is a bit of a misnomer here, we want a type variable that @@ -681,7 +729,7 @@ impl<'a> Resolver<'a> { vecmap(generics, |generic| { // Map the generic to a fresh type variable let id = self.interner.next_type_variable_id(); - let typevar = Shared::new(TypeBinding::Unbound(id)); + let typevar = TypeVariable::unbound(id); let span = generic.0.span(); // Check for name collisions of this generic @@ -790,10 +838,10 @@ impl<'a> Resolver<'a> { }); } - // 'pub_allowed' also implies 'pub' is required on return types - if self.pub_allowed(func) + // 'pub' is required on return types for entry point functions + if self.is_entry_point_function(func) && return_type.as_ref() != &Type::Unit - && func.def.return_visibility != Visibility::Public + && func.def.return_visibility == Visibility::Private { self.push_err(ResolverError::NecessaryPub { ident: func.name_ident().clone() }); } @@ -846,12 +894,9 @@ impl<'a> Resolver<'a> { } /// True if the 'pub' keyword is allowed on parameters in this function + /// 'pub' on function parameters is only allowed for entry point functions fn pub_allowed(&self, func: &NoirFunction) -> bool { - if self.in_contract { - !func.def.is_unconstrained - } else { - func.name() == MAIN_FUNCTION - } + self.is_entry_point_function(func) } fn is_entry_point_function(&self, func: &NoirFunction) -> bool { @@ -927,10 +972,7 @@ impl<'a> Resolver<'a> { found.into_iter().collect() } - fn find_numeric_generics_in_type( - typ: &Type, - found: &mut BTreeMap>, - ) { + fn find_numeric_generics_in_type(typ: &Type, found: &mut BTreeMap) { match typ { Type::FieldElement | Type::Integer(_, _) @@ -941,7 +983,7 @@ impl<'a> Resolver<'a> { | Type::Constant(_) | Type::NamedGeneric(_, _) | Type::NotConstant - | Type::TraitAsType(_) + | Type::TraitAsType(..) | Type::Forall(_, _) => (), Type::Array(length, element_type) => { @@ -1201,8 +1243,9 @@ impl<'a> Resolver<'a> { HirLiteral::Array(HirArrayLiteral::Repeated { repeated_element, length }) } - Literal::Integer(integer) => HirLiteral::Integer(integer), + Literal::Integer(integer, sign) => HirLiteral::Integer(integer, sign), Literal::Str(str) => HirLiteral::Str(str), + Literal::RawStr(str, _) => HirLiteral::Str(str), Literal::FmtStr(str) => self.resolve_fmt_str_literal(str, expr.span), Literal::Unit => HirLiteral::Unit, }), @@ -1500,8 +1543,8 @@ impl<'a> Resolver<'a> { self.interner.get_struct(type_id) } - pub fn get_trait(&self, trait_id: TraitId) -> Trait { - self.interner.get_trait(trait_id) + pub fn get_trait_mut(&mut self, trait_id: TraitId) -> &mut Trait { + self.interner.get_trait_mut(trait_id) } fn lookup(&mut self, path: Path) -> Result { @@ -1544,9 +1587,9 @@ impl<'a> Resolver<'a> { } /// Lookup a given trait by name/path. - fn lookup_trait_or_error(&mut self, path: Path) -> Option { + fn lookup_trait_or_error(&mut self, path: Path) -> Option<&mut Trait> { match self.lookup(path) { - Ok(trait_id) => Some(self.get_trait(trait_id)), + Ok(trait_id) => Some(self.get_trait_mut(trait_id)), Err(error) => { self.push_err(error); None @@ -1586,27 +1629,39 @@ impl<'a> Resolver<'a> { &mut self, path: &Path, ) -> Option<(HirExpression, Type)> { - if let Some(trait_id) = self.trait_id { - if path.kind == PathKind::Plain && path.segments.len() == 2 { - let name = &path.segments[0].0.contents; - let method = &path.segments[1]; + let trait_id = self.trait_id?; - if name == SELF_TYPE_NAME { - let the_trait = self.interner.get_trait(trait_id); + if path.kind == PathKind::Plain && path.segments.len() == 2 { + let name = &path.segments[0].0.contents; + let method = &path.segments[1]; - if let Some(method) = the_trait.find_method(method.clone()) { - let self_type = Type::TypeVariable( - the_trait.self_type_typevar, - crate::TypeVariableKind::Normal, - ); - return Some((HirExpression::TraitMethodReference(method), self_type)); - } - } + if name == SELF_TYPE_NAME { + let the_trait = self.interner.get_trait(trait_id); + let method = the_trait.find_method(method.0.contents.as_str())?; + let self_type = self.self_type.clone()?; + return Some((HirExpression::TraitMethodReference(method), self_type)); } } None } + // this resolves TraitName::some_static_method + fn resolve_trait_static_method(&mut self, path: &Path) -> Option<(HirExpression, Type)> { + if path.kind == PathKind::Plain && path.segments.len() == 2 { + let method = &path.segments[1]; + + let mut trait_path = path.clone(); + trait_path.pop(); + let trait_id = self.lookup(trait_path).ok()?; + let the_trait = self.interner.get_trait(trait_id); + + let method = the_trait.find_method(method.0.contents.as_str())?; + let self_type = Type::type_variable(the_trait.self_type_typevar_id); + return Some((HirExpression::TraitMethodReference(method), self_type)); + } + None + } + // this resolves a static trait method T::trait_method by iterating over the where clause fn resolve_trait_method_by_named_generic( &mut self, @@ -1630,7 +1685,7 @@ impl<'a> Resolver<'a> { { let the_trait = self.interner.get_trait(trait_id); if let Some(method) = - the_trait.find_method(path.segments.last().unwrap().clone()) + the_trait.find_method(path.segments.last().unwrap().0.contents.as_str()) { let self_type = self.resolve_type(typ.clone()); return Some((HirExpression::TraitMethodReference(method), self_type)); @@ -1643,6 +1698,7 @@ impl<'a> Resolver<'a> { fn resolve_trait_generic_path(&mut self, path: &Path) -> Option<(HirExpression, Type)> { self.resolve_trait_static_method_by_self(path) + .or_else(|| self.resolve_trait_static_method(path)) .or_else(|| self.resolve_trait_method_by_named_generic(path)) } @@ -1664,10 +1720,7 @@ impl<'a> Resolver<'a> { fn eval_global_as_array_length(&mut self, global: StmtId) -> u64 { let stmt = match self.interner.statement(&global) { HirStatement::Let(let_expr) => let_expr, - other => { - dbg!(other); - return 0; - } + _ => return 0, }; let length = stmt.expression; @@ -1689,7 +1742,7 @@ impl<'a> Resolver<'a> { span: Span, ) -> Result> { match self.interner.expression(&rhs) { - HirExpression::Literal(HirLiteral::Integer(int)) => { + HirExpression::Literal(HirLiteral::Integer(int, false)) => { int.try_into_u128().ok_or(Some(ResolverError::IntegerTooLarge { span })) } _other => Err(Some(ResolverError::InvalidArrayLengthExpr { span })), @@ -1786,6 +1839,7 @@ impl<'a> Resolver<'a> { self.verify_type_valid_for_program_input(element); } } + UnresolvedTypeData::Parenthesized(typ) => self.verify_type_valid_for_program_input(typ), } } diff --git a/compiler/noirc_frontend/src/hir/resolution/structs.rs b/compiler/noirc_frontend/src/hir/resolution/structs.rs new file mode 100644 index 0000000000..72a7b73643 --- /dev/null +++ b/compiler/noirc_frontend/src/hir/resolution/structs.rs @@ -0,0 +1,53 @@ +use std::collections::BTreeMap; + +use fm::FileId; +use iter_extended::vecmap; + +use crate::{ + graph::CrateId, + hir::{ + def_collector::dc_crate::{CompilationError, UnresolvedStruct}, + def_map::ModuleId, + Context, + }, + node_interner::StructId, + Generics, Ident, Type, +}; + +use super::{errors::ResolverError, path_resolver::StandardPathResolver, resolver::Resolver}; + +/// Create the mappings from TypeId -> StructType +/// so that expressions can access the fields of structs +pub(crate) fn resolve_structs( + context: &mut Context, + structs: BTreeMap, + crate_id: CrateId, +) -> Vec<(CompilationError, FileId)> { + let mut errors: Vec<(CompilationError, FileId)> = vec![]; + // Resolve each field in each struct. + // Each struct should already be present in the NodeInterner after def collection. + for (type_id, typ) in structs { + let file_id = typ.file_id; + let (generics, fields, resolver_errors) = resolve_struct_fields(context, crate_id, typ); + errors.extend(vecmap(resolver_errors, |err| (err.into(), file_id))); + context.def_interner.update_struct(type_id, |struct_def| { + struct_def.set_fields(fields); + struct_def.generics = generics; + }); + } + errors +} + +fn resolve_struct_fields( + context: &mut Context, + krate: CrateId, + unresolved: UnresolvedStruct, +) -> (Generics, Vec<(Ident, Type)>, Vec) { + let path_resolver = + StandardPathResolver::new(ModuleId { local_id: unresolved.module_id, krate }); + let file_id = unresolved.file_id; + let (generics, fields, errors) = + Resolver::new(&mut context.def_interner, &path_resolver, &context.def_maps, file_id) + .resolve_struct_fields(unresolved.struct_def); + (generics, fields, errors) +} diff --git a/compiler/noirc_frontend/src/hir/resolution/traits.rs b/compiler/noirc_frontend/src/hir/resolution/traits.rs new file mode 100644 index 0000000000..54d2630c72 --- /dev/null +++ b/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -0,0 +1,461 @@ +use std::collections::{BTreeMap, HashSet}; + +use fm::FileId; +use iter_extended::vecmap; +use noirc_errors::Location; + +use crate::{ + graph::CrateId, + hir::{ + def_collector::{ + dc_crate::{ + check_methods_signatures, CompilationError, UnresolvedTrait, UnresolvedTraitImpl, + }, + errors::{DefCollectorErrorKind, DuplicateType}, + }, + def_map::{CrateDefMap, ModuleDefId, ModuleId}, + Context, + }, + hir_def::traits::{TraitConstant, TraitFunction, TraitImpl, TraitType}, + node_interner::{FuncId, NodeInterner, TraitId}, + Path, Shared, TraitItem, Type, TypeBinding, TypeVariableKind, +}; + +use super::{ + functions, get_module_mut, get_struct_type, + path_resolver::{PathResolver, StandardPathResolver}, + resolver::Resolver, + take_errors, +}; + +/// Create the mappings from TypeId -> TraitType +/// so that expressions can access the elements of traits +pub(crate) fn resolve_traits( + context: &mut Context, + traits: BTreeMap, + crate_id: CrateId, +) -> Vec<(CompilationError, FileId)> { + for (trait_id, unresolved_trait) in &traits { + context.def_interner.push_empty_trait(*trait_id, unresolved_trait); + } + let mut res: Vec<(CompilationError, FileId)> = vec![]; + for (trait_id, unresolved_trait) in traits { + // Resolve order + // 1. Trait Types ( Trait constants can have a trait type, therefore types before constants) + let _ = resolve_trait_types(context, crate_id, &unresolved_trait); + // 2. Trait Constants ( Trait's methods can use trait types & constants, therefore they should be after) + let _ = resolve_trait_constants(context, crate_id, &unresolved_trait); + // 3. Trait Methods + let (methods, errors) = + resolve_trait_methods(context, trait_id, crate_id, &unresolved_trait); + res.extend(errors); + context.def_interner.update_trait(trait_id, |trait_def| { + trait_def.set_methods(methods); + }); + } + res +} + +fn resolve_trait_types( + _context: &mut Context, + _crate_id: CrateId, + _unresolved_trait: &UnresolvedTrait, +) -> (Vec, Vec<(CompilationError, FileId)>) { + // TODO + (vec![], vec![]) +} +fn resolve_trait_constants( + _context: &mut Context, + _crate_id: CrateId, + _unresolved_trait: &UnresolvedTrait, +) -> (Vec, Vec<(CompilationError, FileId)>) { + // TODO + (vec![], vec![]) +} + +fn resolve_trait_methods( + context: &mut Context, + trait_id: TraitId, + crate_id: CrateId, + unresolved_trait: &UnresolvedTrait, +) -> (Vec, Vec<(CompilationError, FileId)>) { + let interner = &mut context.def_interner; + let def_maps = &mut context.def_maps; + + let path_resolver = StandardPathResolver::new(ModuleId { + local_id: unresolved_trait.module_id, + krate: crate_id, + }); + let file = def_maps[&crate_id].file_id(unresolved_trait.module_id); + + let mut functions = vec![]; + let mut resolver_errors = vec![]; + + for item in &unresolved_trait.trait_def.items { + if let TraitItem::Function { + name, + generics, + parameters, + return_type, + where_clause, + body: _, + } = item + { + let the_trait = interner.get_trait(trait_id); + let self_type = + Type::TypeVariable(the_trait.self_type_typevar.clone(), TypeVariableKind::Normal); + + let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); + resolver.add_generics(generics); + resolver.set_self_type(Some(self_type)); + + let func_id = unresolved_trait.method_ids[&name.0.contents]; + let (_, func_meta) = resolver.resolve_trait_function( + name, + parameters, + return_type, + where_clause, + func_id, + ); + resolver.interner.push_fn_meta(func_meta, func_id); + + let arguments = vecmap(parameters, |param| resolver.resolve_type(param.1.clone())); + let return_type = resolver.resolve_type(return_type.get_type().into_owned()); + + let mut generics = vecmap(resolver.get_generics(), |(_, type_var, _)| match &*type_var + .borrow() + { + TypeBinding::Unbound(id) => (*id, type_var.clone()), + TypeBinding::Bound(binding) => unreachable!("Trait generic was bound to {binding}"), + }); + + // Ensure the trait is generic over the Self type as well + let the_trait = resolver.interner.get_trait(trait_id); + generics.push((the_trait.self_type_typevar_id, the_trait.self_type_typevar.clone())); + + let default_impl_list: Vec<_> = unresolved_trait + .fns_with_default_impl + .functions + .iter() + .filter(|(_, _, q)| q.name() == name.0.contents) + .collect(); + + let default_impl = if default_impl_list.len() == 1 { + Some(Box::new(default_impl_list[0].2.clone())) + } else { + None + }; + + let no_environment = Box::new(Type::Unit); + let function_type = Type::Function(arguments, Box::new(return_type), no_environment); + + functions.push(TraitFunction { + name: name.clone(), + typ: Type::Forall(generics, Box::new(function_type)), + span: name.span(), + default_impl, + default_impl_file_id: unresolved_trait.file_id, + default_impl_module_id: unresolved_trait.module_id, + }); + + let errors = resolver.take_errors().into_iter(); + resolver_errors.extend(errors.map(|resolution_error| (resolution_error.into(), file))); + } + } + (functions, resolver_errors) +} + +fn collect_trait_impl_methods( + interner: &mut NodeInterner, + def_maps: &BTreeMap, + crate_id: CrateId, + trait_id: TraitId, + trait_impl: &mut UnresolvedTraitImpl, +) -> Vec<(CompilationError, FileId)> { + // In this Vec methods[i] corresponds to trait.methods[i]. If the impl has no implementation + // for a particular method, the default implementation will be added at that slot. + let mut ordered_methods = Vec::new(); + + // check whether the trait implementation is in the same crate as either the trait or the type + let mut errors = + check_trait_impl_crate_coherence(interner, trait_id, trait_impl, crate_id, def_maps); + // set of function ids that have a corresponding method in the trait + let mut func_ids_in_trait = HashSet::new(); + + // Temporarily take ownership of the trait's methods so we can iterate over them + // while also mutating the interner + let the_trait = interner.get_trait_mut(trait_id); + let methods = std::mem::take(&mut the_trait.methods); + + for method in &methods { + let overrides: Vec<_> = trait_impl + .methods + .functions + .iter() + .filter(|(_, _, f)| f.name() == method.name.0.contents) + .collect(); + + if overrides.is_empty() { + if let Some(default_impl) = &method.default_impl { + let func_id = interner.push_empty_fn(); + let module = ModuleId { local_id: trait_impl.module_id, krate: crate_id }; + let location = Location::new(default_impl.def.span, trait_impl.file_id); + interner.push_function(func_id, &default_impl.def, module, location); + func_ids_in_trait.insert(func_id); + ordered_methods.push(( + method.default_impl_module_id, + func_id, + *default_impl.clone(), + )); + } else { + let error = DefCollectorErrorKind::TraitMissingMethod { + trait_name: interner.get_trait(trait_id).name.clone(), + method_name: method.name.clone(), + trait_impl_span: trait_impl.object_type.span.expect("type must have a span"), + }; + errors.push((error.into(), trait_impl.file_id)); + } + } else { + for (_, func_id, _) in &overrides { + func_ids_in_trait.insert(*func_id); + } + + if overrides.len() > 1 { + let error = DefCollectorErrorKind::Duplicate { + typ: DuplicateType::TraitAssociatedFunction, + first_def: overrides[0].2.name_ident().clone(), + second_def: overrides[1].2.name_ident().clone(), + }; + errors.push((error.into(), trait_impl.file_id)); + } + + ordered_methods.push(overrides[0].clone()); + } + } + + // Restore the methods that were taken before the for loop + let the_trait = interner.get_trait_mut(trait_id); + the_trait.set_methods(methods); + + // Emit MethodNotInTrait error for methods in the impl block that + // don't have a corresponding method signature defined in the trait + for (_, func_id, func) in &trait_impl.methods.functions { + if !func_ids_in_trait.contains(func_id) { + let error = DefCollectorErrorKind::MethodNotInTrait { + trait_name: the_trait.name.clone(), + impl_method: func.name_ident().clone(), + }; + errors.push((error.into(), trait_impl.file_id)); + } + } + + trait_impl.methods.functions = ordered_methods; + trait_impl.methods.trait_id = Some(trait_id); + errors +} + +fn collect_trait_impl( + context: &mut Context, + crate_id: CrateId, + trait_impl: &mut UnresolvedTraitImpl, +) -> Vec<(CompilationError, FileId)> { + let interner = &mut context.def_interner; + let def_maps = &mut context.def_maps; + let mut errors: Vec<(CompilationError, FileId)> = vec![]; + let unresolved_type = trait_impl.object_type.clone(); + let module = ModuleId { local_id: trait_impl.module_id, krate: crate_id }; + trait_impl.trait_id = + match resolve_trait_by_path(def_maps, module, trait_impl.trait_path.clone()) { + Ok(trait_id) => Some(trait_id), + Err(error) => { + errors.push((error.into(), trait_impl.file_id)); + None + } + }; + + if let Some(trait_id) = trait_impl.trait_id { + errors + .extend(collect_trait_impl_methods(interner, def_maps, crate_id, trait_id, trait_impl)); + + let path_resolver = StandardPathResolver::new(module); + let file = def_maps[&crate_id].file_id(trait_impl.module_id); + let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); + resolver.add_generics(&trait_impl.generics); + let typ = resolver.resolve_type(unresolved_type); + errors.extend(take_errors(trait_impl.file_id, resolver)); + + if let Some(struct_type) = get_struct_type(&typ) { + let struct_type = struct_type.borrow(); + let module = get_module_mut(def_maps, struct_type.id.module_id()); + + for (_, method_id, method) in &trait_impl.methods.functions { + // If this method was already declared, remove it from the module so it cannot + // be accessed with the `TypeName::method` syntax. We'll check later whether the + // object types in each method overlap or not. If they do, we issue an error. + // If not, that is specialization which is allowed. + if module.declare_function(method.name_ident().clone(), *method_id).is_err() { + module.remove_function(method.name_ident()); + } + } + } + } + errors +} + +pub(crate) fn collect_trait_impls( + context: &mut Context, + crate_id: CrateId, + collected_impls: &mut [UnresolvedTraitImpl], +) -> Vec<(CompilationError, FileId)> { + collected_impls + .iter_mut() + .flat_map(|trait_impl| collect_trait_impl(context, crate_id, trait_impl)) + .collect() +} + +fn check_trait_impl_crate_coherence( + interner: &mut NodeInterner, + trait_id: TraitId, + trait_impl: &UnresolvedTraitImpl, + current_crate: CrateId, + def_maps: &BTreeMap, +) -> Vec<(CompilationError, FileId)> { + let mut errors: Vec<(CompilationError, FileId)> = vec![]; + + let module = ModuleId { krate: current_crate, local_id: trait_impl.module_id }; + let file = def_maps[¤t_crate].file_id(trait_impl.module_id); + let path_resolver = StandardPathResolver::new(module); + let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); + + let object_crate = match resolver.resolve_type(trait_impl.object_type.clone()) { + Type::Struct(struct_type, _) => struct_type.borrow().id.krate(), + _ => CrateId::Dummy, + }; + + let the_trait = interner.get_trait(trait_id); + if current_crate != the_trait.crate_id && current_crate != object_crate { + let error = DefCollectorErrorKind::TraitImplOrphaned { + span: trait_impl.object_type.span.expect("object type must have a span"), + }; + errors.push((error.into(), trait_impl.file_id)); + } + + errors +} + +pub(crate) fn resolve_trait_by_path( + def_maps: &BTreeMap, + module: ModuleId, + path: Path, +) -> Result { + let path_resolver = StandardPathResolver::new(module); + + match path_resolver.resolve(def_maps, path.clone()) { + Ok(ModuleDefId::TraitId(trait_id)) => Ok(trait_id), + Ok(_) => Err(DefCollectorErrorKind::NotATrait { not_a_trait_name: path }), + Err(_) => Err(DefCollectorErrorKind::TraitNotFound { trait_path: path }), + } +} +pub(crate) fn resolve_trait_impls( + context: &mut Context, + traits: Vec, + crate_id: CrateId, + errors: &mut Vec<(CompilationError, FileId)>, +) -> Vec<(FileId, FuncId)> { + let interner = &mut context.def_interner; + let mut methods = Vec::<(FileId, FuncId)>::new(); + + for trait_impl in traits { + let unresolved_type = trait_impl.object_type; + let local_mod_id = trait_impl.module_id; + let module_id = ModuleId { krate: crate_id, local_id: local_mod_id }; + let path_resolver = StandardPathResolver::new(module_id); + + let self_type_span = unresolved_type.span; + + let mut resolver = + Resolver::new(interner, &path_resolver, &context.def_maps, trait_impl.file_id); + resolver.add_generics(&trait_impl.generics); + let self_type = resolver.resolve_type(unresolved_type.clone()); + let generics = resolver.get_generics().to_vec(); + + let impl_id = interner.next_trait_impl_id(); + + let mut impl_methods = functions::resolve_function_set( + interner, + crate_id, + &context.def_maps, + trait_impl.methods.clone(), + Some(self_type.clone()), + Some(impl_id), + generics.clone(), + errors, + ); + + let maybe_trait_id = trait_impl.trait_id; + if let Some(trait_id) = maybe_trait_id { + for (_, func) in &impl_methods { + interner.set_function_trait(*func, self_type.clone(), trait_id); + } + } + + if matches!(self_type, Type::MutableReference(_)) { + let span = self_type_span.unwrap_or_else(|| trait_impl.trait_path.span()); + let error = DefCollectorErrorKind::MutableReferenceInTraitImpl { span }; + errors.push((error.into(), trait_impl.file_id)); + } + + let mut new_resolver = + Resolver::new(interner, &path_resolver, &context.def_maps, trait_impl.file_id); + + new_resolver.set_generics(generics); + new_resolver.set_self_type(Some(self_type.clone())); + + if let Some(trait_id) = maybe_trait_id { + check_methods_signatures( + &mut new_resolver, + &impl_methods, + trait_id, + trait_impl.generics.len(), + errors, + ); + + let where_clause = trait_impl + .where_clause + .into_iter() + .flat_map(|item| new_resolver.resolve_trait_constraint(item)) + .collect(); + + let resolved_trait_impl = Shared::new(TraitImpl { + ident: trait_impl.trait_path.last_segment().clone(), + typ: self_type.clone(), + trait_id, + file: trait_impl.file_id, + where_clause, + methods: vecmap(&impl_methods, |(_, func_id)| *func_id), + }); + + if let Err((prev_span, prev_file)) = interner.add_trait_implementation( + self_type.clone(), + trait_id, + impl_id, + resolved_trait_impl, + ) { + let error = DefCollectorErrorKind::OverlappingImpl { + typ: self_type.clone(), + span: self_type_span.unwrap_or_else(|| trait_impl.trait_path.span()), + }; + errors.push((error.into(), trait_impl.file_id)); + + // The 'previous impl defined here' note must be a separate error currently + // since it may be in a different file and all errors have the same file id. + let error = DefCollectorErrorKind::OverlappingImplNote { span: prev_span }; + errors.push((error.into(), prev_file)); + } + + methods.append(&mut impl_methods); + } + } + + methods +} diff --git a/compiler/noirc_frontend/src/hir/resolution/type_aliases.rs b/compiler/noirc_frontend/src/hir/resolution/type_aliases.rs new file mode 100644 index 0000000000..f66f6c8dfa --- /dev/null +++ b/compiler/noirc_frontend/src/hir/resolution/type_aliases.rs @@ -0,0 +1,33 @@ +use super::{path_resolver::StandardPathResolver, resolver::Resolver}; +use crate::{ + graph::CrateId, + hir::{ + def_collector::dc_crate::{CompilationError, UnresolvedTypeAlias}, + def_map::ModuleId, + Context, + }, + node_interner::TypeAliasId, +}; +use fm::FileId; +use std::collections::BTreeMap; + +pub(crate) fn resolve_type_aliases( + context: &mut Context, + type_aliases: BTreeMap, + crate_id: CrateId, +) -> Vec<(CompilationError, FileId)> { + let mut errors: Vec<(CompilationError, FileId)> = vec![]; + for (type_id, unresolved_typ) in type_aliases { + let path_resolver = StandardPathResolver::new(ModuleId { + local_id: unresolved_typ.module_id, + krate: crate_id, + }); + let file = unresolved_typ.file_id; + let (typ, generics, resolver_errors) = + Resolver::new(&mut context.def_interner, &path_resolver, &context.def_maps, file) + .resolve_type_aliases(unresolved_typ.type_alias_def); + errors.extend(resolver_errors.iter().cloned().map(|e| (e.into(), file))); + context.def_interner.set_type_alias(type_id, typ, generics); + } + errors +} diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index 74f076212f..f715489515 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -10,8 +10,8 @@ use crate::{ }, types::Type, }, - node_interner::{DefinitionKind, ExprId, FuncId, TraitId, TraitMethodId}, - BinaryOpKind, Signedness, TypeBinding, TypeVariableKind, UnaryOp, + node_interner::{DefinitionKind, ExprId, FuncId, TraitId, TraitImplKind, TraitMethodId}, + BinaryOpKind, Signedness, TypeBinding, TypeBindings, TypeVariableKind, UnaryOp, }; use super::{errors::TypeCheckError, TypeChecker}; @@ -114,7 +114,7 @@ impl<'interner> TypeChecker<'interner> { Type::Array(Box::new(length), Box::new(elem_type)) } HirLiteral::Bool(_) => Type::Bool, - HirLiteral::Integer(_) => Type::polymorphic_integer(self.interner), + HirLiteral::Integer(_, _) => Type::polymorphic_integer(self.interner), HirLiteral::Str(string) => { let len = Type::Constant(string.len() as u64); Type::String(Box::new(len)) @@ -289,15 +289,23 @@ impl<'interner> TypeChecker<'interner> { } HirExpression::TraitMethodReference(method) => { let the_trait = self.interner.get_trait(method.trait_id); - let method = &the_trait.methods[method.method_index]; - - let typ = Type::Function( - method.arguments.clone(), - Box::new(method.return_type.clone()), - Box::new(Type::Unit), - ); + let typ2 = &the_trait.methods[method.method_index].typ; + let (typ, mut bindings) = typ2.instantiate(self.interner); + + // We must also remember to apply these substitutions to the object_type + // referenced by the selected trait impl, if one has yet to be selected. + let impl_kind = self.interner.get_selected_impl_for_ident(*expr_id); + if let Some(TraitImplKind::Assumed { object_type }) = impl_kind { + let the_trait = self.interner.get_trait(method.trait_id); + let object_type = object_type.substitute(&bindings); + bindings.insert( + the_trait.self_type_typevar_id, + (the_trait.self_type_typevar.clone(), object_type.clone()), + ); + self.interner + .select_impl_for_ident(*expr_id, TraitImplKind::Assumed { object_type }); + } - let (typ, bindings) = typ.instantiate(self.interner); self.interner.store_instantiation_bindings(*expr_id, bindings); typ } @@ -546,7 +554,7 @@ impl<'interner> TypeChecker<'interner> { HirMethodReference::TraitMethodId(method) => { let the_trait = self.interner.get_trait(method.trait_id); let method = &the_trait.methods[method.method_index]; - (method.get_type(), method.arguments.len()) + (method.typ.clone(), method.arguments().len()) } }; @@ -778,7 +786,11 @@ impl<'interner> TypeChecker<'interner> { })); } - if other.try_bind_to_polymorphic_int(int).is_ok() || other == &Type::Error { + let mut bindings = TypeBindings::new(); + if other.try_bind_to_polymorphic_int(int, &mut bindings).is_ok() + || other == &Type::Error + { + Type::apply_type_bindings(bindings); Ok(Bool) } else { Err(TypeCheckError::TypeMismatchWithSource { @@ -894,7 +906,9 @@ impl<'interner> TypeChecker<'interner> { } } } - Type::TraitAsType(_trait) => { + // TODO: We should allow method calls on `impl Trait`s eventually. + // For now it is fine since they are only allowed on return types. + Type::TraitAsType(..) => { self.errors.push(TypeCheckError::UnresolvedMethodCall { method_name: method_name.to_string(), object_type: object_type.clone(), @@ -1009,7 +1023,7 @@ impl<'interner> TypeChecker<'interner> { let env_type = self.interner.next_type_variable(); let expected = Type::Function(args, Box::new(ret.clone()), Box::new(env_type)); - if let Err(error) = binding.borrow_mut().bind_to(expected, span) { + if let Err(error) = binding.try_bind(expected, span) { self.errors.push(error); } ret @@ -1077,7 +1091,11 @@ impl<'interner> TypeChecker<'interner> { })); } - if other.try_bind_to_polymorphic_int(int).is_ok() || other == &Type::Error { + let mut bindings = TypeBindings::new(); + if other.try_bind_to_polymorphic_int(int, &mut bindings).is_ok() + || other == &Type::Error + { + Type::apply_type_bindings(bindings); Ok(other.clone()) } else { Err(TypeCheckError::TypeMismatchWithSource { @@ -1167,6 +1185,10 @@ impl<'interner> TypeChecker<'interner> { match op { crate::UnaryOp::Minus => { + if rhs_type.is_unsigned() { + self.errors + .push(TypeCheckError::InvalidUnaryOp { kind: rhs_type.to_string(), span }); + } let expected = Type::polymorphic_integer(self.interner); rhs_type.unify(&expected, &mut self.errors, || TypeCheckError::InvalidUnaryOp { kind: rhs_type.to_string(), diff --git a/compiler/noirc_frontend/src/hir/type_check/mod.rs b/compiler/noirc_frontend/src/hir/type_check/mod.rs index 19d9d37037..9599104709 100644 --- a/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -101,8 +101,8 @@ pub fn type_check_func(interner: &mut NodeInterner, func_id: FuncId) -> Vec TypeChecker<'interner> { expr_span: range_span, }); - let fresh_id = self.interner.next_type_variable_id(); - let type_variable = Shared::new(TypeBinding::Unbound(fresh_id)); - let expected_type = Type::TypeVariable(type_variable, TypeVariableKind::IntegerOrField); + let expected_type = Type::polymorphic_integer(self.interner); self.unify(&start_range_type, &expected_type, || { TypeCheckError::TypeCannotBeUsed { @@ -350,7 +347,7 @@ impl<'interner> TypeChecker<'interner> { let expr = self.interner.expression(rhs_expr); let span = self.interner.expr_span(rhs_expr); match expr { - HirExpression::Literal(HirLiteral::Integer(value)) => { + HirExpression::Literal(HirLiteral::Integer(value, false)) => { let v = value.to_u128(); if let Type::Integer(_, bit_count) = annotated_type { let max = 1 << bit_count; diff --git a/compiler/noirc_frontend/src/hir_def/expr.rs b/compiler/noirc_frontend/src/hir_def/expr.rs index 755817ba1e..ef1c3af7ac 100644 --- a/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/compiler/noirc_frontend/src/hir_def/expr.rs @@ -78,7 +78,7 @@ impl HirBinaryOp { pub enum HirLiteral { Array(HirArrayLiteral), Bool(bool), - Integer(FieldElement), + Integer(FieldElement, bool), //true for negative integer and false for positive Str(String), FmtStr(String, Vec), Unit, diff --git a/compiler/noirc_frontend/src/hir_def/traits.rs b/compiler/noirc_frontend/src/hir_def/traits.rs index 062f505c17..ea9c2e2928 100644 --- a/compiler/noirc_frontend/src/hir_def/traits.rs +++ b/compiler/noirc_frontend/src/hir_def/traits.rs @@ -1,4 +1,4 @@ -use std::rc::Rc; +use std::collections::HashMap; use crate::{ graph::CrateId, @@ -11,9 +11,7 @@ use noirc_errors::Span; #[derive(Clone, Debug, PartialEq, Eq)] pub struct TraitFunction { pub name: Ident, - pub generics: Vec<(Rc, TypeVariable, Span)>, - pub arguments: Vec, - pub return_type: Type, + pub typ: Type, pub span: Span, pub default_impl: Option>, pub default_impl_file_id: fm::FileId, @@ -37,7 +35,7 @@ pub struct TraitType { /// Represents a trait in the type system. Each instance of this struct /// will be shared across all Type::Trait variants that represent /// the same trait. -#[derive(Debug, Eq, Clone)] +#[derive(Debug, Eq)] pub struct Trait { /// A unique id representing this trait type. Used to check if two /// struct traits are equal. @@ -46,6 +44,13 @@ pub struct Trait { pub crate_id: CrateId, pub methods: Vec, + + /// Maps method_name -> method id. + /// This map is separate from methods since TraitFunction ids + /// are created during collection where we don't yet have all + /// the information needed to create the full TraitFunction. + pub method_ids: HashMap, + pub constants: Vec, pub types: Vec, @@ -60,7 +65,7 @@ pub struct Trait { pub self_type_typevar_id: TypeVariableId, pub self_type_typevar: TypeVariable, } - +#[derive(Debug)] pub struct TraitImpl { pub ident: Ident, pub typ: Type, @@ -101,36 +106,13 @@ impl PartialEq for Trait { } impl Trait { - pub fn new( - id: TraitId, - name: Ident, - crate_id: CrateId, - span: Span, - generics: Generics, - self_type_typevar_id: TypeVariableId, - self_type_typevar: TypeVariable, - ) -> Trait { - Trait { - id, - name, - crate_id, - span, - methods: Vec::new(), - constants: Vec::new(), - types: Vec::new(), - generics, - self_type_typevar_id, - self_type_typevar, - } - } - pub fn set_methods(&mut self, methods: Vec) { self.methods = methods; } - pub fn find_method(&self, name: Ident) -> Option { + pub fn find_method(&self, name: &str) -> Option { for (idx, method) in self.methods.iter().enumerate() { - if method.name == name { + if &method.name == name { return Some(TraitMethodId { trait_id: self.id, method_index: idx }); } } @@ -145,12 +127,33 @@ impl std::fmt::Display for Trait { } impl TraitFunction { - pub fn get_type(&self) -> Type { - Type::Function( - self.arguments.clone(), - Box::new(self.return_type.clone()), - Box::new(Type::Unit), - ) - .generalize() + pub fn arguments(&self) -> &[Type] { + match &self.typ { + Type::Function(args, _, _) => args, + Type::Forall(_, typ) => match typ.as_ref() { + Type::Function(args, _, _) => args, + _ => unreachable!("Trait function does not have a function type"), + }, + _ => unreachable!("Trait function does not have a function type"), + } + } + + pub fn generics(&self) -> &[(TypeVariableId, TypeVariable)] { + match &self.typ { + Type::Function(..) => &[], + Type::Forall(generics, _) => generics, + _ => unreachable!("Trait function does not have a function type"), + } + } + + pub fn return_type(&self) -> &Type { + match &self.typ { + Type::Function(_, return_type, _) => return_type, + Type::Forall(_, typ) => match typ.as_ref() { + Type::Function(_, return_type, _) => return_type, + _ => unreachable!("Trait function does not have a function type"), + }, + _ => unreachable!("Trait function does not have a function type"), + } } } diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 46818626a1..977293ec67 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -6,18 +6,15 @@ use std::{ use crate::{ hir::type_check::TypeCheckError, - node_interner::{ExprId, NodeInterner, TypeAliasId}, + node_interner::{ExprId, NodeInterner, TraitId, TypeAliasId}, }; use iter_extended::vecmap; -use noirc_errors::Span; +use noirc_errors::{Location, Span}; use noirc_printable_type::PrintableType; use crate::{node_interner::StructId, Ident, Signedness}; -use super::{ - expr::{HirCallExpression, HirExpression, HirIdent}, - traits::Trait, -}; +use super::expr::{HirCallExpression, HirExpression, HirIdent}; #[derive(Debug, PartialEq, Eq, Clone, Hash)] pub enum Type { @@ -65,7 +62,10 @@ pub enum Type { /// different argument types each time. TypeVariable(TypeVariable, TypeVariableKind), - TraitAsType(Trait), + /// `impl Trait` when used in a type position. + /// These are only matched based on the TraitId. The trait name paramer is only + /// used for displaying error messages using the name of the trait. + TraitAsType(TraitId, /*name:*/ Rc), /// NamedGenerics are the 'T' or 'U' in a user-defined generic function /// like `fn foo(...) {}`. Unlike TypeVariables, they cannot be bound over. @@ -75,7 +75,7 @@ pub enum Type { /// the environment should be `Unit` by default, /// for closures it should contain a `Tuple` type with the captured /// variable types. - Function(Vec, Box, Box), + Function(Vec, /*return_type:*/ Box, /*environment:*/ Box), /// &mut T MutableReference(Box), @@ -132,7 +132,7 @@ impl Type { Type::FmtString(_, _) | Type::Unit | Type::TypeVariable(_, _) - | Type::TraitAsType(_) + | Type::TraitAsType(..) | Type::NamedGeneric(_, _) | Type::Function(_, _, _) | Type::MutableReference(_) @@ -166,7 +166,7 @@ pub struct StructType { fields: Vec<(Ident, Type)>, pub generics: Generics, - pub span: Span, + pub location: Location, } /// Corresponds to generic lists such as `` in the source @@ -191,11 +191,12 @@ impl StructType { pub fn new( id: StructId, name: Ident, - span: Span, + + location: Location, fields: Vec<(Ident, Type)>, generics: Generics, ) -> StructType { - StructType { id, fields, name, span, generics } + StructType { id, fields, name, location, generics } } /// To account for cyclic references between structs, a struct's @@ -298,7 +299,7 @@ impl std::fmt::Display for TypeAliasType { write!(f, "{}", self.name)?; if !self.generics.is_empty() { - let generics = vecmap(&self.generics, |(_, binding)| binding.borrow().to_string()); + let generics = vecmap(&self.generics, |(_, binding)| binding.0.borrow().to_string()); write!(f, "{}", generics.join(", "))?; } @@ -413,7 +414,66 @@ pub enum TypeVariableKind { /// A TypeVariable is a mutable reference that is either /// bound to some type, or unbound with a given TypeVariableId. -pub type TypeVariable = Shared; +#[derive(Debug, PartialEq, Eq, Clone, Hash)] +pub struct TypeVariable(Shared); + +impl TypeVariable { + pub fn unbound(id: TypeVariableId) -> Self { + TypeVariable(Shared::new(TypeBinding::Unbound(id))) + } + + /// Bind this type variable to a value. + /// + /// Panics if this TypeVariable is already Bound. + /// Also Panics if the ID of this TypeVariable occurs within the given + /// binding, as that would cause an infinitely recursive type. + pub fn bind(&self, typ: Type) { + let id = match &*self.0.borrow() { + TypeBinding::Bound(binding) => { + unreachable!("TypeVariable::bind, cannot bind bound var {} to {}", binding, typ) + } + TypeBinding::Unbound(id) => *id, + }; + + assert!(!typ.occurs(id)); + *self.0.borrow_mut() = TypeBinding::Bound(typ); + } + + pub fn try_bind(&self, binding: Type, span: Span) -> Result<(), TypeCheckError> { + let id = match &*self.0.borrow() { + TypeBinding::Bound(binding) => { + unreachable!("Expected unbound, found bound to {binding}") + } + TypeBinding::Unbound(id) => *id, + }; + + if binding.occurs(id) { + Err(TypeCheckError::TypeAnnotationsNeeded { span }) + } else { + *self.0.borrow_mut() = TypeBinding::Bound(binding); + Ok(()) + } + } + + /// Borrows this TypeVariable to (e.g.) manually match on the inner TypeBinding. + pub fn borrow(&self) -> std::cell::Ref { + self.0.borrow() + } + + /// Unbind this type variable, setting it to Unbound(id). + /// + /// This is generally a logic error to use outside of monomorphization. + pub fn unbind(&self, id: TypeVariableId) { + *self.0.borrow_mut() = TypeBinding::Unbound(id); + } + + /// Forcibly bind a type variable to a new type - even if the type + /// variable is already bound to a different type. This generally + /// a logic error to use outside of monomorphization. + pub fn force_bind(&self, typ: Type) { + *self.0.borrow_mut() = TypeBinding::Bound(typ); + } +} /// TypeBindings are the mutable insides of a TypeVariable. /// They are either bound to some type, or are unbound. @@ -427,24 +487,6 @@ impl TypeBinding { pub fn is_unbound(&self) -> bool { matches!(self, TypeBinding::Unbound(_)) } - - pub fn bind_to(&mut self, binding: Type, span: Span) -> Result<(), TypeCheckError> { - match self { - TypeBinding::Bound(_) => panic!("Tried to bind an already bound type variable!"), - TypeBinding::Unbound(id) => { - if binding.occurs(*id) { - Err(TypeCheckError::TypeAnnotationsNeeded { span }) - } else { - *self = TypeBinding::Bound(binding); - Ok(()) - } - } - } - } - - pub fn unbind(&mut self, id: TypeVariableId) { - *self = TypeBinding::Unbound(id); - } } /// A unique ID used to differentiate different type variables @@ -461,7 +503,8 @@ impl Type { } pub fn type_variable(id: TypeVariableId) -> Type { - Type::TypeVariable(Shared::new(TypeBinding::Unbound(id)), TypeVariableKind::Normal) + let var = TypeVariable(Shared::new(TypeBinding::Unbound(id))); + Type::TypeVariable(var, TypeVariableKind::Normal) } /// Returns a TypeVariable(_, TypeVariableKind::Constant(length)) to bind to @@ -469,13 +512,15 @@ impl Type { pub fn constant_variable(length: u64, interner: &mut NodeInterner) -> Type { let id = interner.next_type_variable_id(); let kind = TypeVariableKind::Constant(length); - Type::TypeVariable(Shared::new(TypeBinding::Unbound(id)), kind) + let var = TypeVariable(Shared::new(TypeBinding::Unbound(id))); + Type::TypeVariable(var, kind) } pub fn polymorphic_integer(interner: &mut NodeInterner) -> Type { let id = interner.next_type_variable_id(); let kind = TypeVariableKind::IntegerOrField; - Type::TypeVariable(Shared::new(TypeBinding::Unbound(id)), kind) + let var = TypeVariable(Shared::new(TypeBinding::Unbound(id))); + Type::TypeVariable(var, kind) } /// A bit of an awkward name for this function - this function returns @@ -484,7 +529,7 @@ impl Type { /// they shouldn't be bound over until monomorphization. pub fn is_bindable(&self) -> bool { match self { - Type::TypeVariable(binding, _) => match &*binding.borrow() { + Type::TypeVariable(binding, _) => match &*binding.0.borrow() { TypeBinding::Bound(binding) => binding.is_bindable(), TypeBinding::Unbound(_) => true, }, @@ -508,7 +553,7 @@ impl Type { // True if the given type is a NamedGeneric with the target_id let named_generic_id_matches_target = |typ: &Type| { if let Type::NamedGeneric(type_variable, _) = typ { - match &*type_variable.borrow() { + match &*type_variable.0.borrow() { TypeBinding::Bound(_) => { unreachable!("Named generics should not be bound until monomorphization") } @@ -530,7 +575,7 @@ impl Type { | Type::NamedGeneric(_, _) | Type::NotConstant | Type::Forall(_, _) - | Type::TraitAsType(_) => false, + | Type::TraitAsType(..) => false, Type::Array(length, elem) => { elem.contains_numeric_typevar(target_id) || named_generic_id_matches_target(length) @@ -608,7 +653,7 @@ impl Type { match self { Type::Forall(generics, _) => generics.len(), Type::TypeVariable(type_variable, _) | Type::NamedGeneric(type_variable, _) => { - match &*type_variable.borrow() { + match &*type_variable.0.borrow() { TypeBinding::Bound(binding) => binding.generic_count(), TypeBinding::Unbound(_) => 0, } @@ -617,31 +662,12 @@ impl Type { } } - /// Takes a monomorphic type and generalizes it over each of the given type variables. - pub(crate) fn generalize_from_variables( - self, - type_vars: HashMap, - ) -> Type { - let polymorphic_type_vars = vecmap(type_vars, |type_var| type_var); - Type::Forall(polymorphic_type_vars, Box::new(self)) - } - /// Takes a monomorphic type and generalizes it over each of the type variables in the /// given type bindings, ignoring what each type variable is bound to in the TypeBindings. pub(crate) fn generalize_from_substitutions(self, type_bindings: TypeBindings) -> Type { let polymorphic_type_vars = vecmap(type_bindings, |(id, (type_var, _))| (id, type_var)); Type::Forall(polymorphic_type_vars, Box::new(self)) } - - /// Takes a monomorphic type and generalizes it over each type variable found within. - /// - /// Note that Noir's type system assumes any Type::Forall are only present at top-level, - /// and thus all type variable's within a type are free. - pub(crate) fn generalize(self) -> Type { - let mut type_variables = HashMap::new(); - self.find_all_unbound_type_variables(&mut type_variables); - self.generalize_from_variables(type_variables) - } } impl std::fmt::Display for Type { @@ -661,23 +687,23 @@ impl std::fmt::Display for Type { Signedness::Signed => write!(f, "i{num_bits}"), Signedness::Unsigned => write!(f, "u{num_bits}"), }, - Type::TypeVariable(id, TypeVariableKind::Normal) => write!(f, "{}", id.borrow()), + Type::TypeVariable(var, TypeVariableKind::Normal) => write!(f, "{}", var.0.borrow()), Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) => { - if let TypeBinding::Unbound(_) = &*binding.borrow() { + if let TypeBinding::Unbound(_) = &*binding.0.borrow() { // Show a Field by default if this TypeVariableKind::IntegerOrField is unbound, since that is // what they bind to by default anyway. It is less confusing than displaying it // as a generic. write!(f, "Field") } else { - write!(f, "{}", binding.borrow()) + write!(f, "{}", binding.0.borrow()) } } Type::TypeVariable(binding, TypeVariableKind::Constant(n)) => { - if let TypeBinding::Unbound(_) = &*binding.borrow() { + if let TypeBinding::Unbound(_) = &*binding.0.borrow() { // TypeVariableKind::Constant(n) binds to Type::Constant(n) by default, so just show that. write!(f, "{n}") } else { - write!(f, "{}", binding.borrow()) + write!(f, "{}", binding.0.borrow()) } } Type::Struct(s, args) => { @@ -688,8 +714,8 @@ impl std::fmt::Display for Type { write!(f, "{}<{}>", s.borrow(), args.join(", ")) } } - Type::TraitAsType(tr) => { - write!(f, "impl {}", tr.name) + Type::TraitAsType(_id, name) => { + write!(f, "impl {}", name) } Type::Tuple(elements) => { let elements = vecmap(elements, ToString::to_string); @@ -702,7 +728,7 @@ impl std::fmt::Display for Type { } Type::Unit => write!(f, "()"), Type::Error => write!(f, "error"), - Type::NamedGeneric(binding, name) => match &*binding.borrow() { + Type::NamedGeneric(binding, name) => match &*binding.0.borrow() { TypeBinding::Bound(binding) => binding.fmt(f), TypeBinding::Unbound(_) if name.is_empty() => write!(f, "_"), TypeBinding::Unbound(_) => write!(f, "{name}"), @@ -761,58 +787,63 @@ pub struct UnificationError; impl Type { /// Try to bind a MaybeConstant variable to self, succeeding if self is a Constant, - /// MaybeConstant, or type variable. - pub fn try_bind_to_maybe_constant( + /// MaybeConstant, or type variable. If successful, the binding is placed in the + /// given TypeBindings map rather than linked immediately. + fn try_bind_to_maybe_constant( &self, var: &TypeVariable, target_length: u64, + bindings: &mut TypeBindings, ) -> Result<(), UnificationError> { - let target_id = match &*var.borrow() { + let target_id = match &*var.0.borrow() { TypeBinding::Bound(_) => unreachable!(), TypeBinding::Unbound(id) => *id, }; - match self { + let this = self.substitute(bindings); + + match &this { Type::Constant(length) if *length == target_length => { - *var.borrow_mut() = TypeBinding::Bound(self.clone()); + bindings.insert(target_id, (var.clone(), this)); Ok(()) } Type::NotConstant => { - *var.borrow_mut() = TypeBinding::Bound(Type::NotConstant); + bindings.insert(target_id, (var.clone(), Type::NotConstant)); Ok(()) } - Type::TypeVariable(binding, kind) => { - let borrow = binding.borrow(); + // A TypeVariable is less specific than a MaybeConstant, so we bind + // to the other type variable instead. + Type::TypeVariable(new_var, kind) => { + let borrow = new_var.0.borrow(); match &*borrow { - TypeBinding::Bound(typ) => typ.try_bind_to_maybe_constant(var, target_length), + TypeBinding::Bound(typ) => { + typ.try_bind_to_maybe_constant(var, target_length, bindings) + } // Avoid infinitely recursive bindings TypeBinding::Unbound(id) if *id == target_id => Ok(()), - TypeBinding::Unbound(_) => match kind { + TypeBinding::Unbound(new_target_id) => match kind { TypeVariableKind::Normal => { - drop(borrow); let clone = Type::TypeVariable( var.clone(), TypeVariableKind::Constant(target_length), ); - *binding.borrow_mut() = TypeBinding::Bound(clone); + bindings.insert(*new_target_id, (new_var.clone(), clone)); Ok(()) } TypeVariableKind::Constant(length) if *length == target_length => { - drop(borrow); let clone = Type::TypeVariable( var.clone(), TypeVariableKind::Constant(target_length), ); - *binding.borrow_mut() = TypeBinding::Bound(clone); + bindings.insert(*new_target_id, (new_var.clone(), clone)); Ok(()) } // The lengths don't match, but neither are set in stone so we can // just set them both to NotConstant. See issue 2370 TypeVariableKind::Constant(_) => { // *length != target_length - drop(borrow); - *var.borrow_mut() = TypeBinding::Bound(Type::NotConstant); - *binding.borrow_mut() = TypeBinding::Bound(Type::NotConstant); + bindings.insert(target_id, (var.clone(), Type::NotConstant)); + bindings.insert(*new_target_id, (new_var.clone(), Type::NotConstant)); Ok(()) } TypeVariableKind::IntegerOrField => Err(UnificationError), @@ -824,44 +855,49 @@ impl Type { } /// Try to bind a PolymorphicInt variable to self, succeeding if self is an integer, field, - /// other PolymorphicInt type, or type variable. - pub fn try_bind_to_polymorphic_int(&self, var: &TypeVariable) -> Result<(), UnificationError> { - let target_id = match &*var.borrow() { + /// other PolymorphicInt type, or type variable. If successful, the binding is placed in the + /// given TypeBindings map rather than linked immediately. + pub fn try_bind_to_polymorphic_int( + &self, + var: &TypeVariable, + bindings: &mut TypeBindings, + ) -> Result<(), UnificationError> { + let target_id = match &*var.0.borrow() { TypeBinding::Bound(_) => unreachable!(), TypeBinding::Unbound(id) => *id, }; - match self { + let this = self.substitute(bindings); + + match &this { Type::FieldElement | Type::Integer(..) => { - *var.borrow_mut() = TypeBinding::Bound(self.clone()); + bindings.insert(target_id, (var.clone(), this)); Ok(()) } Type::TypeVariable(self_var, TypeVariableKind::IntegerOrField) => { - let borrow = self_var.borrow(); + let borrow = self_var.0.borrow(); match &*borrow { - TypeBinding::Bound(typ) => typ.try_bind_to_polymorphic_int(var), + TypeBinding::Bound(typ) => typ.try_bind_to_polymorphic_int(var, bindings), // Avoid infinitely recursive bindings TypeBinding::Unbound(id) if *id == target_id => Ok(()), TypeBinding::Unbound(_) => { - drop(borrow); - *var.borrow_mut() = TypeBinding::Bound(self.clone()); + bindings.insert(target_id, (var.clone(), this.clone())); Ok(()) } } } Type::TypeVariable(binding, TypeVariableKind::Normal) => { - let borrow = binding.borrow(); + let borrow = binding.0.borrow(); match &*borrow { - TypeBinding::Bound(typ) => typ.try_bind_to_polymorphic_int(var), + TypeBinding::Bound(typ) => typ.try_bind_to_polymorphic_int(var, bindings), // Avoid infinitely recursive bindings TypeBinding::Unbound(id) if *id == target_id => Ok(()), - TypeBinding::Unbound(_) => { - drop(borrow); - // PolymorphicInt is more specific than TypeVariable so we bind the type - // variable to PolymorphicInt instead. + TypeBinding::Unbound(new_target_id) => { + // IntegerOrField is more specific than TypeVariable so we bind the type + // variable to IntegerOrField instead. let clone = Type::TypeVariable(var.clone(), TypeVariableKind::IntegerOrField); - *binding.borrow_mut() = TypeBinding::Bound(clone); + bindings.insert(*new_target_id, (binding.clone(), clone)); Ok(()) } } @@ -870,102 +906,113 @@ impl Type { } } - pub fn try_bind_to(&self, var: &TypeVariable) -> Result<(), UnificationError> { - let target_id = match &*var.borrow() { + /// Try to bind the given type variable to self. Although the given type variable + /// is expected to be of TypeVariableKind::Normal, this binding can still fail + /// if the given type variable occurs within `self` as that would create a recursive type. + /// + /// If successful, the binding is placed in the + /// given TypeBindings map rather than linked immediately. + fn try_bind_to( + &self, + var: &TypeVariable, + bindings: &mut TypeBindings, + ) -> Result<(), UnificationError> { + let target_id = match &*var.0.borrow() { TypeBinding::Bound(_) => unreachable!(), TypeBinding::Unbound(id) => *id, }; - if let Some(binding) = self.get_inner_type_variable() { + let this = self.substitute(bindings); + + if let Some(binding) = this.get_inner_type_variable() { match &*binding.borrow() { - TypeBinding::Bound(typ) => return typ.try_bind_to(var), + TypeBinding::Bound(typ) => return typ.try_bind_to(var, bindings), // Don't recursively bind the same id to itself TypeBinding::Unbound(id) if *id == target_id => return Ok(()), _ => (), } } - // Check if the target id occurs within self before binding. Otherwise this could + // Check if the target id occurs within `this` before binding. Otherwise this could // cause infinitely recursive types - if self.occurs(target_id) { + if this.occurs(target_id) { Err(UnificationError) } else { - *var.borrow_mut() = TypeBinding::Bound(self.clone()); + bindings.insert(target_id, (var.clone(), this.clone())); Ok(()) } } fn get_inner_type_variable(&self) -> Option> { match self { - Type::TypeVariable(var, _) | Type::NamedGeneric(var, _) => Some(var.clone()), + Type::TypeVariable(var, _) | Type::NamedGeneric(var, _) => Some(var.0.clone()), _ => None, } } /// Try to unify this type with another, setting any type variables found - /// equal to the other type in the process. Unification is more strict - /// than sub-typing but less strict than Eq. Returns true if the unification - /// succeeded. Note that any bindings performed in a failed unification are - /// not undone. This may cause further type errors later on. + /// equal to the other type in the process. When comparing types, unification + /// (including try_unify) are almost always preferred over Type::eq as unification + /// will correctly handle generic types. pub fn unify( &self, expected: &Type, errors: &mut Vec, make_error: impl FnOnce() -> TypeCheckError, ) { - if let Err(UnificationError) = self.try_unify(expected) { - errors.push(make_error()); + let mut bindings = TypeBindings::new(); + + match self.try_unify(expected, &mut bindings) { + Ok(()) => { + // Commit any type bindings on success + Self::apply_type_bindings(bindings); + } + Err(UnificationError) => errors.push(make_error()), } } /// `try_unify` is a bit of a misnomer since although errors are not committed, /// any unified bindings are on success. - pub fn try_unify(&self, other: &Type) -> Result<(), UnificationError> { + pub fn try_unify( + &self, + other: &Type, + bindings: &mut TypeBindings, + ) -> Result<(), UnificationError> { use Type::*; use TypeVariableKind as Kind; match (self, other) { (Error, _) | (_, Error) => Ok(()), - (TypeVariable(binding, Kind::IntegerOrField), other) - | (other, TypeVariable(binding, Kind::IntegerOrField)) => { - // If it is already bound, unify against what it is bound to - if let TypeBinding::Bound(link) = &*binding.borrow() { - return link.try_unify(other); - } - - // Otherwise, check it is unified against an integer and bind it - other.try_bind_to_polymorphic_int(binding) + (TypeVariable(var, Kind::IntegerOrField), other) + | (other, TypeVariable(var, Kind::IntegerOrField)) => { + other.try_unify_to_type_variable(var, bindings, |bindings| { + other.try_bind_to_polymorphic_int(var, bindings) + }) } - (TypeVariable(binding, Kind::Normal), other) - | (other, TypeVariable(binding, Kind::Normal)) => { - if let TypeBinding::Bound(link) = &*binding.borrow() { - return link.try_unify(other); - } - - other.try_bind_to(binding) + (TypeVariable(var, Kind::Normal), other) | (other, TypeVariable(var, Kind::Normal)) => { + other.try_unify_to_type_variable(var, bindings, |bindings| { + other.try_bind_to(var, bindings) + }) } - (TypeVariable(binding, Kind::Constant(length)), other) - | (other, TypeVariable(binding, Kind::Constant(length))) => { - if let TypeBinding::Bound(link) = &*binding.borrow() { - return link.try_unify(other); - } - - other.try_bind_to_maybe_constant(binding, *length) - } + (TypeVariable(var, Kind::Constant(length)), other) + | (other, TypeVariable(var, Kind::Constant(length))) => other + .try_unify_to_type_variable(var, bindings, |bindings| { + other.try_bind_to_maybe_constant(var, *length, bindings) + }), (Array(len_a, elem_a), Array(len_b, elem_b)) => { - len_a.try_unify(len_b)?; - elem_a.try_unify(elem_b) + len_a.try_unify(len_b, bindings)?; + elem_a.try_unify(elem_b, bindings) } - (String(len_a), String(len_b)) => len_a.try_unify(len_b), + (String(len_a), String(len_b)) => len_a.try_unify(len_b, bindings), (FmtString(len_a, elements_a), FmtString(len_b, elements_b)) => { - len_a.try_unify(len_b)?; - elements_a.try_unify(elements_b) + len_a.try_unify(len_b, bindings)?; + elements_a.try_unify(elements_b, bindings) } (Tuple(elements_a), Tuple(elements_b)) => { @@ -973,7 +1020,7 @@ impl Type { Err(UnificationError) } else { for (a, b) in elements_a.iter().zip(elements_b) { - a.try_unify(b)?; + a.try_unify(b, bindings)?; } Ok(()) } @@ -985,7 +1032,7 @@ impl Type { (Struct(id_a, args_a), Struct(id_b, args_b)) => { if id_a == id_b && args_a.len() == args_b.len() { for (a, b) in args_a.iter().zip(args_b) { - a.try_unify(b)?; + a.try_unify(b, bindings)?; } Ok(()) } else { @@ -993,26 +1040,20 @@ impl Type { } } - (NamedGeneric(binding, _), other) if !binding.borrow().is_unbound() => { - if let TypeBinding::Bound(link) = &*binding.borrow() { - link.try_unify(other) - } else { - unreachable!("If guard ensures binding is bound") - } - } - - (other, NamedGeneric(binding, _)) if !binding.borrow().is_unbound() => { - if let TypeBinding::Bound(link) = &*binding.borrow() { - other.try_unify(link) + (NamedGeneric(binding, _), other) | (other, NamedGeneric(binding, _)) + if !binding.0.borrow().is_unbound() => + { + if let TypeBinding::Bound(link) = &*binding.0.borrow() { + link.try_unify(other, bindings) } else { unreachable!("If guard ensures binding is bound") } } (NamedGeneric(binding_a, name_a), NamedGeneric(binding_b, name_b)) => { - // Unbound NamedGenerics are caught by the checks above - assert!(binding_a.borrow().is_unbound()); - assert!(binding_b.borrow().is_unbound()); + // Bound NamedGenerics are caught by the check above + assert!(binding_a.0.borrow().is_unbound()); + assert!(binding_b.0.borrow().is_unbound()); if name_a == name_b { Ok(()) @@ -1024,17 +1065,19 @@ impl Type { (Function(params_a, ret_a, env_a), Function(params_b, ret_b, env_b)) => { if params_a.len() == params_b.len() { for (a, b) in params_a.iter().zip(params_b.iter()) { - a.try_unify(b)?; + a.try_unify(b, bindings)?; } - env_a.try_unify(env_b)?; - ret_b.try_unify(ret_a) + env_a.try_unify(env_b, bindings)?; + ret_b.try_unify(ret_a, bindings) } else { Err(UnificationError) } } - (MutableReference(elem_a), MutableReference(elem_b)) => elem_a.try_unify(elem_b), + (MutableReference(elem_a), MutableReference(elem_b)) => { + elem_a.try_unify(elem_b, bindings) + } (other_a, other_b) => { if other_a == other_b { @@ -1046,6 +1089,34 @@ impl Type { } } + /// Try to unify a type variable to `self`. + /// This is a helper function factored out from try_unify. + fn try_unify_to_type_variable( + &self, + type_variable: &TypeVariable, + bindings: &mut TypeBindings, + + // Bind the type variable to a type. This is factored out since depending on the + // TypeVariableKind, there are different methods to check whether the variable can + // bind to the given type or not. + bind_variable: impl FnOnce(&mut TypeBindings) -> Result<(), UnificationError>, + ) -> Result<(), UnificationError> { + match &*type_variable.0.borrow() { + // If it is already bound, unify against what it is bound to + TypeBinding::Bound(link) => link.try_unify(self, bindings), + TypeBinding::Unbound(id) => { + // We may have already "bound" this type variable in this call to + // try_unify, so check those bindings as well. + match bindings.get(id) { + Some((_, binding)) => binding.clone().try_unify(self, bindings), + + // Otherwise, bind it + None => bind_variable(bindings), + } + } + } + } + /// Similar to `unify` but if the check fails this will attempt to coerce the /// argument to the target type. When this happens, the given expression is wrapped in /// a new expression to convert its type. E.g. `array` -> `array.as_slice()` @@ -1059,10 +1130,14 @@ impl Type { errors: &mut Vec, make_error: impl FnOnce() -> TypeCheckError, ) { - if let Err(UnificationError) = self.try_unify(expected) { + let mut bindings = TypeBindings::new(); + + if let Err(UnificationError) = self.try_unify(expected, &mut bindings) { if !self.try_array_to_slice_coercion(expected, expression, interner) { errors.push(make_error()); } + } else { + Type::apply_type_bindings(bindings); } } @@ -1085,8 +1160,10 @@ impl Type { if matches!(size1, Type::Constant(_)) && matches!(size2, Type::NotConstant) { // Still have to ensure the element types match. // Don't need to issue an error here if not, it will be done in unify_with_coercions - if element1.try_unify(element2).is_ok() { + let mut bindings = TypeBindings::new(); + if element1.try_unify(element2, &mut bindings).is_ok() { convert_array_expression_to_slice(expression, this, target, interner); + Self::apply_type_bindings(bindings); return true; } } @@ -1094,6 +1171,14 @@ impl Type { false } + /// Apply the given type bindings, making them permanently visible for each + /// clone of each type variable bound. + pub fn apply_type_bindings(bindings: TypeBindings) { + for (type_variable, binding) in bindings.values() { + type_variable.bind(binding.clone()); + } + } + /// If this type is a Type::Constant (used in array lengths), or is bound /// to a Type::Constant, return the constant as a u64. pub fn evaluate_to_u64(&self) -> Option { @@ -1194,7 +1279,7 @@ impl Type { | Type::Integer(_, _) | Type::Bool | Type::Unit - | Type::TraitAsType(_) + | Type::TraitAsType(..) | Type::Constant(_) | Type::NotConstant | Type::Error => (), @@ -1229,7 +1314,7 @@ impl Type { } Type::Forall(_, typ) => typ.find_all_unbound_type_variables(type_variables), Type::TypeVariable(type_variable, _) | Type::NamedGeneric(type_variable, _) => { - match &*type_variable.borrow() { + match &*type_variable.0.borrow() { TypeBinding::Bound(binding) => { binding.find_all_unbound_type_variables(type_variables); } @@ -1251,7 +1336,7 @@ impl Type { return self.clone(); } - let substitute_binding = |binding: &TypeVariable| match &*binding.borrow() { + let substitute_binding = |binding: &TypeVariable| match &*binding.0.borrow() { TypeBinding::Bound(binding) => binding.substitute(type_bindings), TypeBinding::Unbound(id) => match type_bindings.get(id) { Some((_, binding)) => binding.clone(), @@ -1287,7 +1372,6 @@ impl Type { let fields = vecmap(fields, |field| field.substitute(type_bindings)); Type::Tuple(fields) } - Type::TraitAsType(_) => todo!(), Type::Forall(typevars, typ) => { // Trying to substitute a variable defined within a nested Forall // is usually impossible and indicative of an error in the type checker somewhere. @@ -1311,6 +1395,7 @@ impl Type { | Type::Integer(_, _) | Type::Bool | Type::Constant(_) + | Type::TraitAsType(..) | Type::Error | Type::NotConstant | Type::Unit => self.clone(), @@ -1327,11 +1412,10 @@ impl Type { let field_occurs = fields.occurs(target_id); len_occurs || field_occurs } - Type::TraitAsType(_) => todo!(), Type::Struct(_, generic_args) => generic_args.iter().any(|arg| arg.occurs(target_id)), Type::Tuple(fields) => fields.iter().any(|field| field.occurs(target_id)), Type::NamedGeneric(binding, _) | Type::TypeVariable(binding, _) => { - match &*binding.borrow() { + match &*binding.0.borrow() { TypeBinding::Bound(binding) => binding.occurs(target_id), TypeBinding::Unbound(id) => *id == target_id, } @@ -1350,6 +1434,7 @@ impl Type { | Type::Integer(_, _) | Type::Bool | Type::Constant(_) + | Type::TraitAsType(..) | Type::Error | Type::NotConstant | Type::Unit => false, @@ -1380,7 +1465,7 @@ impl Type { } Tuple(args) => Tuple(vecmap(args, |arg| arg.follow_bindings())), TypeVariable(var, _) | NamedGeneric(var, _) => { - if let TypeBinding::Bound(typ) = &*var.borrow() { + if let TypeBinding::Bound(typ) = &*var.0.borrow() { return typ.follow_bindings(); } self.clone() @@ -1397,7 +1482,7 @@ impl Type { // Expect that this function should only be called on instantiated types Forall(..) => unreachable!(), - TraitAsType(_) + TraitAsType(..) | FieldElement | Integer(_, _) | Bool @@ -1485,7 +1570,7 @@ impl From<&Type> for PrintableType { Signedness::Signed => PrintableType::SignedInteger { width: *bit_width }, }, Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) => { - match &*binding.borrow() { + match &*binding.0.borrow() { TypeBinding::Bound(typ) => typ.into(), TypeBinding::Unbound(_) => Type::default_int_type().into(), } @@ -1505,7 +1590,7 @@ impl From<&Type> for PrintableType { let fields = vecmap(fields, |(name, typ)| (name, typ.into())); PrintableType::Struct { fields, name: struct_type.name.to_string() } } - Type::TraitAsType(_) => unreachable!(), + Type::TraitAsType(..) => unreachable!(), Type::Tuple(_) => todo!("printing tuple types is not yet implemented"), Type::TypeVariable(_, _) => unreachable!(), Type::NamedGeneric(..) => unreachable!(), diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index be24c1249c..fd8168e36c 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -126,6 +126,7 @@ impl<'a> Lexer<'a> { Some(']') => self.single_char_token(Token::RightBracket), Some('"') => self.eat_string_literal(), Some('f') => self.eat_format_string_or_alpha_numeric(), + Some('r') => self.eat_raw_string_or_alpha_numeric(), Some('#') => self.eat_attribute(), Some(ch) if ch.is_ascii_alphanumeric() || ch == '_' => self.eat_alpha_numeric(ch), Some(ch) => { @@ -322,11 +323,29 @@ impl<'a> Lexer<'a> { let start = self.position; let integer_str = self.eat_while(Some(initial_char), |ch| { - ch.is_ascii_digit() | ch.is_ascii_hexdigit() | (ch == 'x') + ch.is_ascii_digit() | ch.is_ascii_hexdigit() | (ch == 'x') | (ch == '_') }); let end = self.position; + // We want to enforce some simple rules about usage of underscores: + // 1. Underscores cannot appear at the end of a integer literal. e.g. 0x123_. + // 2. There cannot be more than one underscore consecutively, e.g. 0x5__5, 5__5. + // + // We're not concerned with an underscore at the beginning of a decimal literal + // such as `_5` as this would be lexed into an ident rather than an integer literal. + let invalid_underscore_location = integer_str.ends_with('_'); + let consecutive_underscores = integer_str.contains("__"); + if invalid_underscore_location || consecutive_underscores { + return Err(LexerErrorKind::InvalidIntegerLiteral { + span: Span::inclusive(start, end), + found: integer_str, + }); + } + + // Underscores needs to be stripped out before the literal can be converted to a `FieldElement. + let integer_str = integer_str.replace('_', ""); + let integer = match FieldElement::try_from_str(&integer_str) { None => { return Err(LexerErrorKind::InvalidIntegerLiteral { @@ -400,6 +419,78 @@ impl<'a> Lexer<'a> { } } + fn eat_raw_string(&mut self) -> SpannedTokenResult { + let start = self.position; + + let beginning_hashes = self.eat_while(None, |ch| ch == '#'); + let beginning_hashes_count = beginning_hashes.chars().count(); + if beginning_hashes_count > 255 { + // too many hashes (unlikely in practice) + // also, Rust disallows 256+ hashes as well + return Err(LexerErrorKind::UnexpectedCharacter { + span: Span::single_char(start + 255), + found: Some('#'), + expected: "\"".to_owned(), + }); + } + + if !self.peek_char_is('"') { + return Err(LexerErrorKind::UnexpectedCharacter { + span: Span::single_char(self.position), + found: self.next_char(), + expected: "\"".to_owned(), + }); + } + self.next_char(); + + let mut str_literal = String::new(); + loop { + let chars = self.eat_while(None, |ch| ch != '"'); + str_literal.push_str(&chars[..]); + if !self.peek_char_is('"') { + return Err(LexerErrorKind::UnexpectedCharacter { + span: Span::single_char(self.position), + found: self.next_char(), + expected: "\"".to_owned(), + }); + } + self.next_char(); + let mut ending_hashes_count = 0; + while let Some('#') = self.peek_char() { + if ending_hashes_count == beginning_hashes_count { + break; + } + self.next_char(); + ending_hashes_count += 1; + } + if ending_hashes_count == beginning_hashes_count { + break; + } else { + str_literal.push('"'); + for _ in 0..ending_hashes_count { + str_literal.push('#'); + } + } + } + + let str_literal_token = Token::RawStr(str_literal, beginning_hashes_count as u8); + + let end = self.position; + Ok(str_literal_token.into_span(start, end)) + } + + fn eat_raw_string_or_alpha_numeric(&mut self) -> SpannedTokenResult { + // Problem: we commit to eating raw strings once we see one or two characters. + // This is unclean, but likely ok in all practical cases, and works with existing + // `Lexer` methods. + let peek1 = self.peek_char().unwrap_or('X'); + let peek2 = self.peek2_char().unwrap_or('X'); + match (peek1, peek2) { + ('#', '#') | ('#', '"') | ('"', _) => self.eat_raw_string(), + _ => self.eat_alpha_numeric('r'), + } + } + fn parse_comment(&mut self, start: u32) -> SpannedTokenResult { let doc_style = match self.peek_char() { Some('!') => { @@ -560,15 +651,18 @@ mod tests { } #[test] - fn test_attribute_with_apostrophe() { - let input = r#"#[test(should_fail_with = "the eagle's feathers")]"#; + fn test_attribute_with_common_punctuation() { + let input = + r#"#[test(should_fail_with = "stmt. q? exclaim! & symbols, 1% shouldn't fail")]"#; let mut lexer = Lexer::new(input); let token = lexer.next_token().unwrap().token().clone(); assert_eq!( token, Token::Attribute(Attribute::Function(FunctionAttribute::Test( - TestScope::ShouldFailWith { reason: "the eagle's feathers".to_owned().into() } + TestScope::ShouldFailWith { + reason: "stmt. q? exclaim! & symbols, 1% shouldn't fail".to_owned().into() + } ))) ); } @@ -854,15 +948,33 @@ mod tests { } #[test] - fn test_eat_hex_int() { - let input = "0x05"; - - let expected = vec![Token::Int(5_i128.into())]; - let mut lexer = Lexer::new(input); + fn test_eat_integer_literals() { + let test_cases: Vec<(&str, Token)> = vec![ + ("0x05", Token::Int(5_i128.into())), + ("5", Token::Int(5_i128.into())), + ("0x1234_5678", Token::Int(0x1234_5678_u128.into())), + ("0x_01", Token::Int(0x1_u128.into())), + ("1_000_000", Token::Int(1_000_000_u128.into())), + ]; - for token in expected.into_iter() { + for (input, expected_token) in test_cases { + let mut lexer = Lexer::new(input); let got = lexer.next_token().unwrap(); - assert_eq!(got, token); + assert_eq!(got.token(), &expected_token); + } + } + + #[test] + fn test_reject_invalid_underscores_in_integer_literal() { + let test_cases: Vec<&str> = vec!["0x05_", "5_", "5__5", "0x5__5"]; + + for input in test_cases { + let mut lexer = Lexer::new(input); + let token = lexer.next_token(); + assert!( + matches!(token, Err(LexerErrorKind::InvalidIntegerLiteral { .. })), + "expected {input} to throw error" + ); } } diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index 72be71865c..e6542c643a 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -15,6 +15,7 @@ pub enum Token { Int(FieldElement), Bool(bool), Str(String), + RawStr(String, u8), FmtStr(String), Keyword(Keyword), IntType(IntType), @@ -157,6 +158,10 @@ impl fmt::Display for Token { Token::Bool(b) => write!(f, "{b}"), Token::Str(ref b) => write!(f, "{b}"), Token::FmtStr(ref b) => write!(f, "f{b}"), + Token::RawStr(ref b, hashes) => { + let h: String = std::iter::once('#').cycle().take(hashes as usize).collect(); + write!(f, "r{h}\"{b}\"{h}") + } Token::Keyword(k) => write!(f, "{k}"), Token::Attribute(ref a) => write!(f, "{a}"), Token::LineComment(ref s, _style) => write!(f, "//{s}"), @@ -227,7 +232,11 @@ impl Token { pub fn kind(&self) -> TokenKind { match *self { Token::Ident(_) => TokenKind::Ident, - Token::Int(_) | Token::Bool(_) | Token::Str(_) | Token::FmtStr(_) => TokenKind::Literal, + Token::Int(_) + | Token::Bool(_) + | Token::Str(_) + | Token::RawStr(..) + | Token::FmtStr(_) => TokenKind::Literal, Token::Keyword(_) => TokenKind::Keyword, Token::Attribute(_) => TokenKind::Attribute, ref tok => TokenKind::Token(tok.clone()), @@ -459,13 +468,8 @@ impl Attribute { .all(|ch| { ch.is_ascii_alphabetic() || ch.is_numeric() - || ch == '_' - || ch == '(' - || ch == ')' - || ch == '=' - || ch == '"' + || ch.is_ascii_punctuation() || ch == ' ' - || ch == '\'' }) .then_some(()); @@ -635,6 +639,7 @@ pub enum Keyword { Assert, AssertEq, Bool, + CallData, Char, CompTime, Constrain, @@ -658,6 +663,7 @@ pub enum Keyword { Open, Pub, Return, + ReturnData, String, Struct, Trait, @@ -676,6 +682,7 @@ impl fmt::Display for Keyword { Keyword::AssertEq => write!(f, "assert_eq"), Keyword::Bool => write!(f, "bool"), Keyword::Char => write!(f, "char"), + Keyword::CallData => write!(f, "call_data"), Keyword::CompTime => write!(f, "comptime"), Keyword::Constrain => write!(f, "constrain"), Keyword::Contract => write!(f, "contract"), @@ -698,6 +705,7 @@ impl fmt::Display for Keyword { Keyword::Open => write!(f, "open"), Keyword::Pub => write!(f, "pub"), Keyword::Return => write!(f, "return"), + Keyword::ReturnData => write!(f, "return_data"), Keyword::String => write!(f, "str"), Keyword::Struct => write!(f, "struct"), Keyword::Trait => write!(f, "trait"), @@ -718,6 +726,7 @@ impl Keyword { "assert" => Keyword::Assert, "assert_eq" => Keyword::AssertEq, "bool" => Keyword::Bool, + "call_data" => Keyword::CallData, "char" => Keyword::Char, "comptime" => Keyword::CompTime, "constrain" => Keyword::Constrain, @@ -741,6 +750,7 @@ impl Keyword { "open" => Keyword::Open, "pub" => Keyword::Pub, "return" => Keyword::Return, + "return_data" => Keyword::ReturnData, "str" => Keyword::String, "struct" => Keyword::Struct, "trait" => Keyword::Trait, diff --git a/compiler/noirc_frontend/src/lib.rs b/compiler/noirc_frontend/src/lib.rs index 74057240de..77107d3e7d 100644 --- a/compiler/noirc_frontend/src/lib.rs +++ b/compiler/noirc_frontend/src/lib.rs @@ -34,3 +34,46 @@ pub use hir_def::types::*; // Unit tests that involve all modules pub mod tests; + +// API for experimental macros feature +pub mod macros_api { + + pub use acvm::FieldElement; + pub use fm::FileId; + pub use noirc_errors::Span; + + pub use crate::graph::CrateId; + pub use crate::hir::def_collector::errors::MacroError; + pub use crate::hir_def::expr::{HirExpression, HirLiteral}; + pub use crate::hir_def::stmt::HirStatement; + pub use crate::node_interner::{NodeInterner, StructId}; + pub use crate::parser::SortedModule; + pub use crate::token::SecondaryAttribute; + + pub use crate::hir::def_map::ModuleDefId; + pub use crate::{ + hir::Context as HirContext, BlockExpression, CallExpression, CastExpression, Distinctness, + Expression, ExpressionKind, FunctionReturnType, Ident, IndexExpression, LetStatement, + Literal, MemberAccessExpression, MethodCallExpression, NoirFunction, Path, PathKind, + Pattern, Statement, UnresolvedType, UnresolvedTypeData, Visibility, + }; + pub use crate::{ + ForLoopStatement, ForRange, FunctionDefinition, FunctionVisibility, ImportStatement, + NoirStruct, Param, PrefixExpression, Signedness, StatementKind, StructType, Type, TypeImpl, + UnaryOp, + }; + + /// Methods to process the AST before and after type checking + pub trait MacroProcessor { + /// Function to manipulate the AST before type checking has been completed. + fn process_untyped_ast( + &self, + ast: SortedModule, + crate_id: &CrateId, + context: &HirContext, + ) -> Result; + /// Function to manipulate the AST after type checking has been completed. + /// The AST after type checking has been done is called the HIR. + fn process_typed_ast(&self, crate_id: &CrateId, context: &mut HirContext); + } +} diff --git a/compiler/noirc_frontend/src/monomorphization/ast.rs b/compiler/noirc_frontend/src/monomorphization/ast.rs index 0a005d766f..5a5f07b0a3 100644 --- a/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -2,7 +2,9 @@ use acvm::FieldElement; use iter_extended::vecmap; use noirc_errors::Location; -use crate::{hir_def::function::FunctionSignature, BinaryOpKind, Distinctness, Signedness}; +use crate::{ + hir_def::function::FunctionSignature, BinaryOpKind, Distinctness, Signedness, Visibility, +}; /// The monomorphized AST is expression-based, all statements are also /// folded into this expression enum. Compared to the HIR, the monomorphized @@ -243,6 +245,7 @@ pub struct Program { /// forwarding to the next phase. pub return_distinctness: Distinctness, pub return_location: Option, + pub return_visibility: Visibility, } impl Program { @@ -251,8 +254,15 @@ impl Program { main_function_signature: FunctionSignature, return_distinctness: Distinctness, return_location: Option, + return_visibility: Visibility, ) -> Program { - Program { functions, main_function_signature, return_distinctness, return_location } + Program { + functions, + main_function_signature, + return_distinctness, + return_location, + return_visibility, + } } pub fn main(&self) -> &Function { diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 57e4e6cdeb..78cde11593 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -105,8 +105,14 @@ pub fn monomorphize(main: node_interner::FuncId, interner: &NodeInterner) -> Pro } let functions = vecmap(monomorphizer.finished_functions, |(_, f)| f); - let FuncMeta { return_distinctness, .. } = interner.function_meta(&main); - Program::new(functions, function_sig, return_distinctness, monomorphizer.return_location) + let FuncMeta { return_distinctness, return_visibility, .. } = interner.function_meta(&main); + Program::new( + functions, + function_sig, + return_distinctness, + monomorphizer.return_location, + return_visibility, + ) } impl<'interner> Monomorphizer<'interner> { @@ -215,7 +221,7 @@ impl<'interner> Monomorphizer<'interner> { fn function(&mut self, f: node_interner::FuncId, id: FuncId) { if let Some((self_type, trait_id)) = self.interner.get_function_trait(&f) { let the_trait = self.interner.get_trait(trait_id); - *the_trait.self_type_typevar.borrow_mut() = TypeBinding::Bound(self_type); + the_trait.self_type_typevar.force_bind(self_type); } let meta = self.interner.function_meta(&f); @@ -225,7 +231,7 @@ impl<'interner> Monomorphizer<'interner> { let body_expr_id = *self.interner.function(&f).as_expr(); let body_return_type = self.interner.id_type(body_expr_id); let return_type = self.convert_type(match meta.return_type() { - Type::TraitAsType(_) => &body_return_type, + Type::TraitAsType(..) => &body_return_type, _ => meta.return_type(), }); @@ -310,10 +316,23 @@ impl<'interner> Monomorphizer<'interner> { )) } HirExpression::Literal(HirLiteral::Bool(value)) => Literal(Bool(value)), - HirExpression::Literal(HirLiteral::Integer(value)) => { - let typ = self.convert_type(&self.interner.id_type(expr)); - let location = self.interner.id_location(expr); - Literal(Integer(value, typ, location)) + HirExpression::Literal(HirLiteral::Integer(value, sign)) => { + if sign { + let typ = self.convert_type(&self.interner.id_type(expr)); + let location = self.interner.id_location(expr); + match typ { + ast::Type::Field => Literal(Integer(-value, typ, location)), + ast::Type::Integer(_, bit_size) => { + let base = 1_u128 << bit_size; + Literal(Integer(FieldElement::from(base) - value, typ, location)) + } + _ => unreachable!("Integer literal must be numeric"), + } + } else { + let typ = self.convert_type(&self.interner.id_type(expr)); + let location = self.interner.id_location(expr); + Literal(Integer(value, typ, location)) + } } HirExpression::Literal(HirLiteral::Array(array)) => match array { HirArrayLiteral::Standard(array) => self.standard_array(expr, array), @@ -701,7 +720,7 @@ impl<'interner> Monomorphizer<'interner> { ast::Type::Slice(element) } } - HirType::TraitAsType(_) => { + HirType::TraitAsType(..) => { unreachable!("All TraitAsType should be replaced before calling convert_type"); } HirType::NamedGeneric(binding, _) => { @@ -712,11 +731,7 @@ impl<'interner> Monomorphizer<'interner> { // Default any remaining unbound type variables. // This should only happen if the variable in question is unused // and within a larger generic type. - // NOTE: Make sure to review this if there is ever type-directed dispatch, - // like automatic solving of traits. It should be fine since it is strictly - // after type checking, but care should be taken that it doesn't change which - // impls are chosen. - *binding.borrow_mut() = TypeBinding::Bound(HirType::default_int_type()); + binding.bind(HirType::default_int_type()); ast::Type::Field } @@ -728,10 +743,6 @@ impl<'interner> Monomorphizer<'interner> { // Default any remaining unbound type variables. // This should only happen if the variable in question is unused // and within a larger generic type. - // NOTE: Make sure to review this if there is ever type-directed dispatch, - // like automatic solving of traits. It should be fine since it is strictly - // after type checking, but care should be taken that it doesn't change which - // impls are chosen. let default = if self.is_range_loop && matches!(kind, TypeVariableKind::IntegerOrField) { Type::default_range_loop_type() @@ -740,7 +751,7 @@ impl<'interner> Monomorphizer<'interner> { }; let monomorphized_default = self.convert_type(&default); - *binding.borrow_mut() = TypeBinding::Bound(default); + binding.bind(default); monomorphized_default } @@ -875,7 +886,6 @@ impl<'interner> Monomorphizer<'interner> { let original_func = Box::new(self.expr(call.func)); let mut arguments = vecmap(&call.arguments, |id| self.expr(*id)); let hir_arguments = vecmap(&call.arguments, |id| self.interner.expression(id)); - let func: Box; let return_type = self.interner.id_type(id); let return_type = self.convert_type(&return_type); @@ -883,10 +893,11 @@ impl<'interner> Monomorphizer<'interner> { if let ast::Expression::Ident(ident) = original_func.as_ref() { if let Definition::Oracle(name) = &ident.definition { - if name.as_str() == "println" { + if name.as_str() == "print" { // Oracle calls are required to be wrapped in an unconstrained function - // Thus, the only argument to the `println` oracle is expected to always be an ident - self.append_printable_type_info(&hir_arguments[0], &mut arguments); + // The first argument to the `print` oracle is a bool, indicating a newline to be inserted at the end of the input + // The second argument is expected to always be an ident + self.append_printable_type_info(&hir_arguments[1], &mut arguments); } } } @@ -895,7 +906,8 @@ impl<'interner> Monomorphizer<'interner> { let func_type = self.interner.id_type(call.func); let func_type = self.convert_type(&func_type); let is_closure = self.is_function_closure(func_type); - if is_closure { + + let func = if is_closure { let local_id = self.next_local_id(); // store the function in a temporary variable before calling it @@ -917,14 +929,13 @@ impl<'interner> Monomorphizer<'interner> { typ: self.convert_type(&self.interner.id_type(call.func)), }); - func = Box::new(ast::Expression::ExtractTupleField( - Box::new(extracted_func.clone()), - 1usize, - )); - let env_argument = ast::Expression::ExtractTupleField(Box::new(extracted_func), 0usize); + let env_argument = + ast::Expression::ExtractTupleField(Box::new(extracted_func.clone()), 0usize); arguments.insert(0, env_argument); + + Box::new(ast::Expression::ExtractTupleField(Box::new(extracted_func), 1usize)) } else { - func = original_func.clone(); + original_func.clone() }; let call = self @@ -1430,12 +1441,12 @@ fn unwrap_struct_type(typ: &HirType) -> Vec<(String, HirType)> { fn perform_instantiation_bindings(bindings: &TypeBindings) { for (var, binding) in bindings.values() { - *var.borrow_mut() = TypeBinding::Bound(binding.clone()); + var.force_bind(binding.clone()); } } fn undo_instantiation_bindings(bindings: TypeBindings) { for (id, (var, _)) in bindings { - *var.borrow_mut() = TypeBinding::Unbound(id); + var.unbind(id); } } diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 300a95f819..236f1e0b51 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -9,7 +9,7 @@ use crate::ast::Ident; use crate::graph::CrateId; use crate::hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait, UnresolvedTypeAlias}; use crate::hir::def_map::{LocalModuleId, ModuleId}; -use crate::hir::StorageSlot; + use crate::hir_def::stmt::HirLetStatement; use crate::hir_def::traits::TraitImpl; use crate::hir_def::traits::{Trait, TraitConstraint}; @@ -22,7 +22,7 @@ use crate::hir_def::{ use crate::token::{Attributes, SecondaryAttribute}; use crate::{ ContractFunctionType, FunctionDefinition, FunctionVisibility, Generics, Shared, TypeAliasType, - TypeBinding, TypeBindings, TypeVariable, TypeVariableId, TypeVariableKind, + TypeBindings, TypeVariable, TypeVariableId, TypeVariableKind, }; /// An arbitrary number to limit the recursion depth when searching for trait impls. @@ -37,6 +37,7 @@ type StructAttributes = Vec; /// each definition or struct, etc. Because it is used on the Hir, the NodeInterner is /// useful in passes where the Hir is used - name resolution, type checking, and /// monomorphization - and it is not useful afterward. +#[derive(Debug)] pub struct NodeInterner { nodes: Arena, func_meta: HashMap, @@ -157,7 +158,7 @@ pub enum TraitImplKind { /// /// Additionally, types can define specialized impls with methods of the same name /// as long as these specialized impls do not overlap. E.g. `impl Struct` and `impl Struct` -#[derive(Default)] +#[derive(Default, Debug)] pub struct Methods { direct: Vec, trait_impl_methods: Vec, @@ -166,6 +167,7 @@ pub struct Methods { /// All the information from a function that is filled out during definition collection rather than /// name resolution. As a result, if information about a function is needed during name resolution, /// this is the only place where it is safe to retrieve it (where all fields are guaranteed to be initialized). +#[derive(Debug, Clone)] pub struct FunctionModifiers { pub name: String, @@ -353,6 +355,7 @@ pub struct DefinitionInfo { pub name: String, pub mutable: bool, pub kind: DefinitionKind, + pub location: Location, } impl DefinitionInfo { @@ -399,10 +402,6 @@ impl DefinitionKind { pub struct GlobalInfo { pub ident: Ident, pub local_id: LocalModuleId, - - /// Global definitions have an associated storage slot if they are defined within - /// a contract. If they're defined elsewhere, this value is None. - pub storage_slot: Option, } impl Default for NodeInterner { @@ -456,6 +455,30 @@ impl NodeInterner { self.id_to_location.insert(expr_id.into(), Location::new(span, file)); } + /// Scans the interner for the item which is located at that [Location] + /// + /// The [Location] may not necessarily point to the beginning of the item + /// so we check if the location's span is contained within the start or end + /// of each items [Span] + pub fn find_location_index(&self, location: Location) -> Option> { + let mut location_candidate: Option<(&Index, &Location)> = None; + + // Note: we can modify this in the future to not do a linear + // scan by storing a separate map of the spans or by sorting the locations. + for (index, interned_location) in self.id_to_location.iter() { + if interned_location.contains(&location) { + if let Some(current_location) = location_candidate { + if interned_location.span.is_smaller(¤t_location.1.span) { + location_candidate = Some((index, interned_location)); + } + } else { + location_candidate = Some((index, interned_location)); + } + } + } + location_candidate.map(|(index, _location)| *index) + } + /// Interns a HIR Function. pub fn push_fn(&mut self, func: HirFunction) -> FuncId { FuncId(self.nodes.insert(Node::Function(func))) @@ -466,29 +489,31 @@ impl NodeInterner { self.id_to_type.insert(expr_id.into(), typ); } - pub fn push_empty_trait(&mut self, type_id: TraitId, typ: &UnresolvedTrait) { + pub fn push_empty_trait(&mut self, type_id: TraitId, unresolved_trait: &UnresolvedTrait) { let self_type_typevar_id = self.next_type_variable_id(); - let self_type_typevar = Shared::new(TypeBinding::Unbound(self_type_typevar_id)); - self.traits.insert( - type_id, - Trait::new( - type_id, - typ.trait_def.name.clone(), - typ.crate_id, - typ.trait_def.span, - vecmap(&typ.trait_def.generics, |_| { - // Temporary type variable ids before the trait is resolved to its actual ids. - // This lets us record how many arguments the type expects so that other types - // can refer to it with generic arguments before the generic parameters themselves - // are resolved. - let id = TypeVariableId(0); - (id, Shared::new(TypeBinding::Unbound(id))) - }), - self_type_typevar_id, - self_type_typevar, - ), - ); + let new_trait = Trait { + id: type_id, + name: unresolved_trait.trait_def.name.clone(), + crate_id: unresolved_trait.crate_id, + span: unresolved_trait.trait_def.span, + generics: vecmap(&unresolved_trait.trait_def.generics, |_| { + // Temporary type variable ids before the trait is resolved to its actual ids. + // This lets us record how many arguments the type expects so that other types + // can refer to it with generic arguments before the generic parameters themselves + // are resolved. + let id = TypeVariableId(0); + (id, TypeVariable::unbound(id)) + }), + self_type_typevar_id, + self_type_typevar: TypeVariable::unbound(self_type_typevar_id), + methods: Vec::new(), + method_ids: unresolved_trait.method_ids.clone(), + constants: Vec::new(), + types: Vec::new(), + }; + + self.traits.insert(type_id, new_trait); } pub fn new_struct( @@ -496,6 +521,7 @@ impl NodeInterner { typ: &UnresolvedStruct, krate: CrateId, local_id: LocalModuleId, + file_id: FileId, ) -> StructId { let struct_id = StructId(ModuleId { krate, local_id }); let name = typ.struct_def.name.clone(); @@ -508,10 +534,11 @@ impl NodeInterner { // can refer to it with generic arguments before the generic parameters themselves // are resolved. let id = TypeVariableId(0); - (id, Shared::new(TypeBinding::Unbound(id))) + (id, TypeVariable::unbound(id)) }); - let new_struct = StructType::new(struct_id, name, typ.struct_def.span, no_fields, generics); + let location = Location::new(typ.struct_def.span, file_id); + let new_struct = StructType::new(struct_id, name, location, no_fields, generics); self.structs.insert(struct_id, Shared::new(new_struct)); self.struct_attributes.insert(struct_id, typ.struct_def.attributes.clone()); struct_id @@ -527,7 +554,7 @@ impl NodeInterner { Type::Error, vecmap(&typ.type_alias_def.generics, |_| { let id = TypeVariableId(0); - (id, Shared::new(TypeBinding::Unbound(id))) + (id, TypeVariable::unbound(id)) }), )); @@ -578,14 +605,8 @@ impl NodeInterner { self.id_to_type.insert(definition_id.into(), typ); } - pub fn push_global( - &mut self, - stmt_id: StmtId, - ident: Ident, - local_id: LocalModuleId, - storage_slot: Option, - ) { - self.globals.insert(stmt_id, GlobalInfo { ident, local_id, storage_slot }); + pub fn push_global(&mut self, stmt_id: StmtId, ident: Ident, local_id: LocalModuleId) { + self.globals.insert(stmt_id, GlobalInfo { ident, local_id }); } /// Intern an empty global stmt. Used for collecting globals @@ -646,13 +667,14 @@ impl NodeInterner { name: String, mutable: bool, definition: DefinitionKind, + location: Location, ) -> DefinitionId { let id = DefinitionId(self.definitions.len()); if let DefinitionKind::Function(func_id) = definition { self.function_definition_ids.insert(func_id, id); } - self.definitions.push(DefinitionInfo { name, mutable, kind: definition }); + self.definitions.push(DefinitionInfo { name, mutable, kind: definition, location }); id } @@ -663,7 +685,8 @@ impl NodeInterner { let mut modifiers = FunctionModifiers::new(); modifiers.name = name; let module = ModuleId::dummy_id(); - self.push_function_definition(id, modifiers, module); + let location = Location::dummy(); + self.push_function_definition(id, modifiers, module, location); id } @@ -672,6 +695,7 @@ impl NodeInterner { id: FuncId, function: &FunctionDefinition, module: ModuleId, + location: Location, ) -> DefinitionId { use ContractFunctionType::*; @@ -685,7 +709,7 @@ impl NodeInterner { contract_function_type: Some(if function.is_open { Open } else { Secret }), is_internal: Some(function.is_internal), }; - self.push_function_definition(id, modifiers, module) + self.push_function_definition(id, modifiers, module, location) } pub fn push_function_definition( @@ -693,11 +717,12 @@ impl NodeInterner { func: FuncId, modifiers: FunctionModifiers, module: ModuleId, + location: Location, ) -> DefinitionId { let name = modifiers.name.clone(); self.function_modifiers.insert(func, modifiers); self.function_modules.insert(func, module); - self.push_definition(name, false, DefinitionKind::Function(func)) + self.push_definition(name, false, DefinitionKind::Function(func), location) } pub fn set_function_trait(&mut self, func: FuncId, self_type: Type, trait_id: TraitId) { @@ -841,12 +866,16 @@ impl NodeInterner { self.structs[&id].clone() } - pub fn get_trait(&self, id: TraitId) -> Trait { - self.traits[&id].clone() + pub fn get_trait(&self, id: TraitId) -> &Trait { + &self.traits[&id] + } + + pub fn get_trait_mut(&mut self, id: TraitId) -> &mut Trait { + self.traits.get_mut(&id).expect("get_trait_mut given invalid TraitId") } - pub fn try_get_trait(&self, id: TraitId) -> Option { - self.traits.get(&id).cloned() + pub fn try_get_trait(&self, id: TraitId) -> Option<&Trait> { + self.traits.get(&id) } pub fn get_type_alias(&self, id: TypeAliasId) -> &TypeAliasType { @@ -870,7 +899,7 @@ impl NodeInterner { let typ = self.id_type(def_id); if let Type::Function(args, ret, env) = &typ { let def = self.definition(def_id); - if let Type::TraitAsType(_trait) = ret.as_ref() { + if let Type::TraitAsType(..) = ret.as_ref() { if let DefinitionKind::Function(func_id) = def.kind { let f = self.function(&func_id); let func_body = f.as_expr(); @@ -984,13 +1013,32 @@ impl NodeInterner { object_type: &Type, trait_id: TraitId, ) -> Result> { - self.lookup_trait_implementation_helper(object_type, trait_id, IMPL_SEARCH_RECURSION_LIMIT) + let (impl_kind, bindings) = self.try_lookup_trait_implementation(object_type, trait_id)?; + Type::apply_type_bindings(bindings); + Ok(impl_kind) + } + + /// Similar to `lookup_trait_implementation` but does not apply any type bindings on success. + pub fn try_lookup_trait_implementation( + &self, + object_type: &Type, + trait_id: TraitId, + ) -> Result<(TraitImplKind, TypeBindings), Vec> { + let mut bindings = TypeBindings::new(); + let impl_kind = self.lookup_trait_implementation_helper( + object_type, + trait_id, + &mut bindings, + IMPL_SEARCH_RECURSION_LIMIT, + )?; + Ok((impl_kind, bindings)) } fn lookup_trait_implementation_helper( &self, object_type: &Type, trait_id: TraitId, + type_bindings: &mut TypeBindings, recursion_limit: u32, ) -> Result> { let make_constraint = || TraitConstraint::new(object_type.clone(), trait_id); @@ -1000,20 +1048,29 @@ impl NodeInterner { return Err(vec![make_constraint()]); } + let object_type = object_type.substitute(type_bindings); + let impls = self.trait_implementation_map.get(&trait_id).ok_or_else(|| vec![make_constraint()])?; for (existing_object_type, impl_kind) in impls { - let (existing_object_type, type_bindings) = existing_object_type.instantiate(self); + let (existing_object_type, instantiation_bindings) = + existing_object_type.instantiate(self); + + let mut fresh_bindings = TypeBindings::new(); + + if object_type.try_unify(&existing_object_type, &mut fresh_bindings).is_ok() { + // The unification was successful so we can append fresh_bindings to our bindings list + type_bindings.extend(fresh_bindings); - if object_type.try_unify(&existing_object_type).is_ok() { if let TraitImplKind::Normal(impl_id) = impl_kind { let trait_impl = self.get_trait_implementation(*impl_id); let trait_impl = trait_impl.borrow(); if let Err(mut errors) = self.validate_where_clause( &trait_impl.where_clause, - &type_bindings, + type_bindings, + &instantiation_bindings, recursion_limit, ) { errors.push(make_constraint()); @@ -1033,14 +1090,20 @@ impl NodeInterner { fn validate_where_clause( &self, where_clause: &[TraitConstraint], - type_bindings: &TypeBindings, + type_bindings: &mut TypeBindings, + instantiation_bindings: &TypeBindings, recursion_limit: u32, ) -> Result<(), Vec> { for constraint in where_clause { - let constraint_type = constraint.typ.substitute(type_bindings); + let constraint_type = constraint.typ.substitute(instantiation_bindings); + let constraint_type = constraint_type.substitute(type_bindings); + self.lookup_trait_implementation_helper( &constraint_type, constraint.trait_id, + // Use a fresh set of type bindings here since the constraint_type originates from + // our impl list, which we don't want to bind to. + &mut TypeBindings::new(), recursion_limit - 1, )?; } @@ -1061,7 +1124,7 @@ impl NodeInterner { trait_id: TraitId, ) -> bool { // Make sure there are no overlapping impls - if self.lookup_trait_implementation(&object_type, trait_id).is_ok() { + if self.try_lookup_trait_implementation(&object_type, trait_id).is_ok() { return false; } @@ -1089,8 +1152,8 @@ impl NodeInterner { let (instantiated_object_type, substitutions) = object_type.instantiate_type_variables(self); - if let Ok(TraitImplKind::Normal(existing)) = - self.lookup_trait_implementation(&instantiated_object_type, trait_id) + if let Ok((TraitImplKind::Normal(existing), _)) = + self.try_lookup_trait_implementation(&instantiated_object_type, trait_id) { let existing_impl = self.get_trait_implementation(existing); let existing_impl = existing_impl.borrow(); @@ -1195,12 +1258,99 @@ impl NodeInterner { self.selected_trait_implementations.insert(ident_id, trait_impl); } - /// Tags the given identifier with the selected trait_impl so that monomorphization - /// can later recover which impl was selected, or alternatively see if it needs to - /// decide which (because the impl was Assumed). + /// Retrieves the impl selected for a given IdentId during name resolution. + /// From type checking and on, the "ident" referred to is changed to a TraitMethodReference node. pub fn get_selected_impl_for_ident(&self, ident_id: ExprId) -> Option { self.selected_trait_implementations.get(&ident_id).cloned() } + + /// For a given [Index] we return [Location] to which we resolved to + /// We currently return None for features not yet implemented + /// TODO(#3659): LSP goto def should error when Ident at Location could not resolve + pub(crate) fn resolve_location(&self, index: impl Into) -> Option { + let node = self.nodes.get(index.into())?; + + match node { + Node::Function(func) => self.resolve_location(func.as_expr()), + Node::Expression(expression) => self.resolve_expression_location(expression), + _ => None, + } + } + + /// Resolves the [Location] of the definition for a given [HirExpression] + /// + /// Note: current the code returns None because some expressions are not yet implemented. + fn resolve_expression_location(&self, expression: &HirExpression) -> Option { + match expression { + HirExpression::Ident(ident) => { + let definition_info = self.definition(ident.id); + match definition_info.kind { + DefinitionKind::Function(func_id) => { + Some(self.function_meta(&func_id).location) + } + DefinitionKind::Local(_local_id) => Some(definition_info.location), + _ => None, + } + } + HirExpression::Constructor(expr) => { + let struct_type = &expr.r#type.borrow(); + + eprintln!("\n -> Resolve Constructor {struct_type:?}\n"); + + Some(struct_type.location) + } + HirExpression::MemberAccess(expr_member_access) => { + self.resolve_struct_member_access(expr_member_access) + } + HirExpression::Call(expr_call) => { + let func = expr_call.func; + self.resolve_location(func) + } + + _ => None, + } + } + + /// Resolves the [Location] of the definition for a given [crate::hir_def::expr::HirMemberAccess] + /// This is used to resolve the location of a struct member access. + /// For example, in the expression `foo.bar` we want to resolve the location of `bar` + /// to the location of the definition of `bar` in the struct `foo`. + fn resolve_struct_member_access( + &self, + expr_member_access: &crate::hir_def::expr::HirMemberAccess, + ) -> Option { + let expr_lhs = &expr_member_access.lhs; + let expr_rhs = &expr_member_access.rhs; + + let found_ident = self.nodes.get(expr_lhs.into())?; + + let ident = match found_ident { + Node::Expression(HirExpression::Ident(ident)) => ident, + _ => return None, + }; + + let definition_info = self.definition(ident.id); + + let local_id = match definition_info.kind { + DefinitionKind::Local(Some(local_id)) => local_id, + _ => return None, + }; + + let constructor_expression = match self.nodes.get(local_id.into()) { + Some(Node::Expression(HirExpression::Constructor(constructor_expression))) => { + constructor_expression + } + _ => return None, + }; + + let struct_type = constructor_expression.r#type.borrow(); + let field_names = struct_type.field_names(); + + match field_names.iter().find(|field_name| field_name.0 == expr_rhs.0) { + Some(found) => Some(Location::new(found.span(), struct_type.location.file)), + None => None, + } + } } impl Methods { @@ -1238,8 +1388,10 @@ impl Methods { match interner.function_meta(&method).typ.instantiate(interner).0 { Type::Function(args, _, _) => { if let Some(object) = args.get(0) { - // TODO #3089: This is dangerous! try_unify may commit type bindings even on failure - if object.try_unify(typ).is_ok() { + let mut bindings = TypeBindings::new(); + + if object.try_unify(typ, &mut bindings).is_ok() { + Type::apply_type_bindings(bindings); return Some(method); } } @@ -1253,7 +1405,7 @@ impl Methods { } /// These are the primitive type variants that we support adding methods to -#[derive(Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] enum TypeMethodKey { /// Fields and integers share methods for ease of use. These methods may still /// accept only fields or integers, it is just that their names may not clash. @@ -1292,6 +1444,6 @@ fn get_type_method_key(typ: &Type) -> Option { | Type::Error | Type::NotConstant | Type::Struct(_, _) - | Type::TraitAsType(_) => None, + | Type::TraitAsType(..) => None, } } diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index 6b8589cc6e..a97637642a 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -414,7 +414,12 @@ fn trait_definition() -> impl NoirParser { .then(trait_body()) .then_ignore(just(Token::RightBrace)) .validate(|(((name, generics), where_clause), items), span, emit| { - emit(ParserError::with_reason(ParserErrorReason::ExperimentalFeature("Traits"), span)); + if !generics.is_empty() { + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("Generic traits"), + span, + )); + } TopLevelStatement::Trait(NoirTrait { name, generics, where_clause, span, items }) }) } @@ -437,7 +442,13 @@ fn trait_constant_declaration() -> impl NoirParser { .then(parse_type()) .then(optional_default_value()) .then_ignore(just(Token::Semicolon)) - .map(|((name, typ), default_value)| TraitItem::Constant { name, typ, default_value }) + .validate(|((name, typ), default_value), span, emit| { + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("Associated constants"), + span, + )); + TraitItem::Constant { name, typ, default_value } + }) } /// trait_function_declaration: 'fn' ident generics '(' declaration_parameters ')' function_return_type @@ -544,10 +555,15 @@ fn function_declaration_parameters() -> impl NoirParser impl NoirParser { - keyword(Keyword::Type) - .ignore_then(ident()) - .then_ignore(just(Token::Semicolon)) - .map(|name| TraitItem::Type { name }) + keyword(Keyword::Type).ignore_then(ident()).then_ignore(just(Token::Semicolon)).validate( + |name, span, emit| { + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("Associated types"), + span, + )); + TraitItem::Type { name } + }, + ) } /// Parses a non-trait implementation, adding a set of methods to a type. @@ -581,11 +597,10 @@ fn trait_implementation() -> impl NoirParser { .then_ignore(just(Token::LeftBrace)) .then(trait_implementation_body()) .then_ignore(just(Token::RightBrace)) - .validate(|args, span, emit| { + .map(|args| { let ((other_args, where_clause), items) = args; let (((impl_generics, trait_name), trait_generics), object_type) = other_args; - emit(ParserError::with_reason(ParserErrorReason::ExperimentalFeature("Traits"), span)); TopLevelStatement::TraitImpl(NoirTraitImpl { impl_generics, trait_name, @@ -616,12 +631,10 @@ fn where_clause() -> impl NoirParser> { trait_bounds: Vec, } - let constraints = parse_type().then_ignore(just(Token::Colon)).then(trait_bounds()).validate( - |(typ, trait_bounds), span, emit| { - emit(ParserError::with_reason(ParserErrorReason::ExperimentalFeature("Traits"), span)); - MultiTraitConstraint { typ, trait_bounds } - }, - ); + let constraints = parse_type() + .then_ignore(just(Token::Colon)) + .then(trait_bounds()) + .map(|(typ, trait_bounds)| MultiTraitConstraint { typ, trait_bounds }); keyword(Keyword::Where) .ignore_then(constraints.separated_by(just(Token::Comma))) @@ -726,21 +739,21 @@ fn token_kind(token_kind: TokenKind) -> impl NoirParser { fn path() -> impl NoirParser { let idents = || ident().separated_by(just(Token::DoubleColon)).at_least(1); - let make_path = |kind| move |segments| Path { segments, kind }; + let make_path = |kind| move |segments, span| Path { segments, kind, span }; let prefix = |key| keyword(key).ignore_then(just(Token::DoubleColon)); - let path_kind = |key, kind| prefix(key).ignore_then(idents()).map(make_path(kind)); + let path_kind = |key, kind| prefix(key).ignore_then(idents()).map_with_span(make_path(kind)); choice(( path_kind(Keyword::Crate, PathKind::Crate), path_kind(Keyword::Dep, PathKind::Dep), - idents().map(make_path(PathKind::Plain)), + idents().map_with_span(make_path(PathKind::Plain)), )) } fn empty_path() -> impl NoirParser { - let make_path = |kind| move |_| Path { segments: Vec::new(), kind }; - let path_kind = |key, kind| keyword(key).map(make_path(kind)); + let make_path = |kind| move |_, span| Path { segments: Vec::new(), kind, span }; + let path_kind = |key, kind| keyword(key).map_with_span(make_path(kind)); choice((path_kind(Keyword::Crate, PathKind::Crate), path_kind(Keyword::Dep, PathKind::Dep))) } @@ -1015,18 +1028,37 @@ fn parse_type_inner( named_type(recursive_type_parser.clone()), named_trait(recursive_type_parser.clone()), array_type(recursive_type_parser.clone()), - recursive_type_parser.clone().delimited_by(just(Token::LeftParen), just(Token::RightParen)), + parenthesized_type(recursive_type_parser.clone()), tuple_type(recursive_type_parser.clone()), function_type(recursive_type_parser.clone()), mutable_reference_type(recursive_type_parser), )) } +fn parenthesized_type( + recursive_type_parser: impl NoirParser, +) -> impl NoirParser { + recursive_type_parser + .delimited_by(just(Token::LeftParen), just(Token::RightParen)) + .map_with_span(|typ, span| UnresolvedType { + typ: UnresolvedTypeData::Parenthesized(Box::new(typ)), + span: span.into(), + }) +} + fn optional_visibility() -> impl NoirParser { - keyword(Keyword::Pub).or_not().map(|opt| match opt { - Some(_) => Visibility::Public, - None => Visibility::Private, - }) + keyword(Keyword::Pub) + .or(keyword(Keyword::CallData)) + .or(keyword(Keyword::ReturnData)) + .or_not() + .map(|opt| match opt { + Some(Token::Keyword(Keyword::Pub)) => Visibility::Public, + Some(Token::Keyword(Keyword::CallData)) | Some(Token::Keyword(Keyword::ReturnData)) => { + Visibility::DataBus + } + None => Visibility::Private, + _ => unreachable!("unexpected token found"), + }) } fn optional_distinctness() -> impl NoirParser { @@ -1177,7 +1209,9 @@ where .ignore_then(type_parser.clone()) .then_ignore(just(Token::RightBracket)) .or_not() - .map_with_span(|t, span| t.unwrap_or_else(|| UnresolvedTypeData::Unit.with_span(span))); + .map_with_span(|t, span| { + t.unwrap_or_else(|| UnresolvedTypeData::Unit.with_span(Span::empty(span.end()))) + }); keyword(Keyword::Fn) .ignore_then(env) @@ -1657,15 +1691,28 @@ fn literal() -> impl NoirParser { Token::Int(x) => ExpressionKind::integer(x), Token::Bool(b) => ExpressionKind::boolean(b), Token::Str(s) => ExpressionKind::string(s), + Token::RawStr(s, hashes) => ExpressionKind::raw_string(s, hashes), Token::FmtStr(s) => ExpressionKind::format_string(s), unexpected => unreachable!("Non-literal {} parsed as a literal", unexpected), }) } +fn literal_with_sign() -> impl NoirParser { + choice(( + literal(), + just(Token::Minus).then(literal()).map(|(_, exp)| match exp { + ExpressionKind::Literal(Literal::Integer(value, sign)) => { + ExpressionKind::Literal(Literal::Integer(value, !sign)) + } + _ => unreachable!(), + }), + )) +} + fn literal_or_collection<'a>( expr_parser: impl ExprParser + 'a, ) -> impl NoirParser + 'a { - choice((literal(), constructor(expr_parser.clone()), array_expr(expr_parser))) + choice((literal_with_sign(), constructor(expr_parser.clone()), array_expr(expr_parser))) } #[cfg(test)] @@ -2242,7 +2289,7 @@ mod test { let hex = parse_with(literal(), "0x05").unwrap(); match (expr_to_lit(int), expr_to_lit(hex)) { - (Literal::Integer(int), Literal::Integer(hex)) => assert_eq!(int, hex), + (Literal::Integer(int, false), Literal::Integer(hex, false)) => assert_eq!(int, hex), _ => unreachable!(), } } @@ -2549,4 +2596,79 @@ mod test { check_cases_with_errors(&cases[..], block(fresh_statement())); } + + #[test] + fn parse_raw_string_expr() { + let cases = vec![ + Case { source: r##" r"foo" "##, expect: r##"r"foo""##, errors: 0 }, + Case { source: r##" r#"foo"# "##, expect: r##"r#"foo"#"##, errors: 0 }, + // backslash + Case { source: r##" r"\\" "##, expect: r##"r"\\""##, errors: 0 }, + Case { source: r##" r#"\"# "##, expect: r##"r#"\"#"##, errors: 0 }, + Case { source: r##" r#"\\"# "##, expect: r##"r#"\\"#"##, errors: 0 }, + Case { source: r##" r#"\\\"# "##, expect: r##"r#"\\\"#"##, errors: 0 }, + // escape sequence + Case { + source: r##" r#"\t\n\\t\\n\\\t\\\n\\\\"# "##, + expect: r##"r#"\t\n\\t\\n\\\t\\\n\\\\"#"##, + errors: 0, + }, + Case { source: r##" r#"\\\\\\\\"# "##, expect: r##"r#"\\\\\\\\"#"##, errors: 0 }, + // mismatch - errors: + Case { source: r###" r#"foo"## "###, expect: r###"r#"foo"#"###, errors: 1 }, + Case { source: r###" r##"foo"# "###, expect: "(none)", errors: 2 }, + // mismatch: short: + Case { source: r###" r"foo"# "###, expect: r###"r"foo""###, errors: 1 }, + Case { source: r###" r#"foo" "###, expect: "(none)", errors: 2 }, + // empty string + Case { source: r####"r"""####, expect: r####"r"""####, errors: 0 }, + Case { source: r####"r###""###"####, expect: r####"r###""###"####, errors: 0 }, + // miscellaneous + Case { source: r###" r#\"foo\"# "###, expect: "plain::r", errors: 2 }, + Case { source: r###" r\"foo\" "###, expect: "plain::r", errors: 1 }, + Case { source: r###" r##"foo"# "###, expect: "(none)", errors: 2 }, + // missing 'r' letter + Case { source: r###" ##"foo"# "###, expect: r#""foo""#, errors: 2 }, + Case { source: r###" #"foo" "###, expect: "plain::foo", errors: 2 }, + // whitespace + Case { source: r###" r #"foo"# "###, expect: "plain::r", errors: 2 }, + Case { source: r###" r# "foo"# "###, expect: "plain::r", errors: 3 }, + Case { source: r###" r#"foo" # "###, expect: "(none)", errors: 2 }, + // after identifier + Case { source: r###" bar#"foo"# "###, expect: "plain::bar", errors: 2 }, + // nested + Case { + source: r###"r##"foo r#"bar"# r"baz" ### bye"##"###, + expect: r###"r##"foo r#"bar"# r"baz" ### bye"##"###, + errors: 0, + }, + ]; + + check_cases_with_errors(&cases[..], expression()); + } + + #[test] + fn parse_raw_string_lit() { + let lit_cases = vec![ + Case { source: r##" r"foo" "##, expect: r##"r"foo""##, errors: 0 }, + Case { source: r##" r#"foo"# "##, expect: r##"r#"foo"#"##, errors: 0 }, + // backslash + Case { source: r##" r"\\" "##, expect: r##"r"\\""##, errors: 0 }, + Case { source: r##" r#"\"# "##, expect: r##"r#"\"#"##, errors: 0 }, + Case { source: r##" r#"\\"# "##, expect: r##"r#"\\"#"##, errors: 0 }, + Case { source: r##" r#"\\\"# "##, expect: r##"r#"\\\"#"##, errors: 0 }, + // escape sequence + Case { + source: r##" r#"\t\n\\t\\n\\\t\\\n\\\\"# "##, + expect: r##"r#"\t\n\\t\\n\\\t\\\n\\\\"#"##, + errors: 0, + }, + Case { source: r##" r#"\\\\\\\\"# "##, expect: r##"r#"\\\\\\\\"#"##, errors: 0 }, + // mismatch - errors: + Case { source: r###" r#"foo"## "###, expect: r###"r#"foo"#"###, errors: 1 }, + Case { source: r###" r##"foo"# "###, expect: "(none)", errors: 2 }, + ]; + + check_cases_with_errors(&lit_cases[..], literal()); + } } diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 6a1cf80acc..3f4755aa0e 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -9,6 +9,7 @@ mod test { use fm::FileId; + use iter_extended::vecmap; use noirc_errors::Location; use crate::hir::def_collector::dc_crate::CompilationError; @@ -38,71 +39,55 @@ mod test { errors.iter().any(|(e, _f)| matches!(e, CompilationError::ParseError(_))) } - pub(crate) fn remove_experimental_feature_warnings( - errors: Vec<(CompilationError, FileId)>, - ) -> Vec<(CompilationError, FileId)> { - errors - .iter() - .filter(|(e, _f)| match e.clone() { - CompilationError::ParseError(parser_error) => !matches!( - parser_error.reason(), - Some(ParserErrorReason::ExperimentalFeature(_)) - ), - _ => true, - }) - .cloned() - .collect() + pub(crate) fn remove_experimental_warnings(errors: &mut Vec<(CompilationError, FileId)>) { + errors.retain(|(error, _)| match error { + CompilationError::ParseError(error) => { + !matches!(error.reason(), Some(ParserErrorReason::ExperimentalFeature(..))) + } + _ => true, + }); } pub(crate) fn get_program( src: &str, ) -> (ParsedModule, Context, Vec<(CompilationError, FileId)>) { let root = std::path::Path::new("/"); - let fm = FileManager::new(root, Box::new(|path| std::fs::read_to_string(path))); - //let fm = FileManager::new(root, Box::new(get_non_stdlib_asset)); + let fm = FileManager::new(root); let graph = CrateGraph::default(); let mut context = Context::new(fm, graph); let root_file_id = FileId::dummy(); let root_crate_id = context.crate_graph.add_crate_root(root_file_id); let (program, parser_errors) = parse_program(src); - let mut errors = remove_experimental_feature_warnings( - parser_errors.iter().cloned().map(|e| (e.into(), root_file_id)).collect(), - ); + let mut errors = vecmap(parser_errors, |e| (e.into(), root_file_id)); + remove_experimental_warnings(&mut errors); + if !has_parser_error(&errors) { // Allocate a default Module for the root, giving it a ModuleId let mut modules: Arena = Arena::default(); let location = Location::new(Default::default(), root_file_id); let root = modules.insert(ModuleData::new(None, location, false)); + let def_map = CrateDefMap { root: LocalModuleId(root), modules, krate: root_crate_id, extern_prelude: BTreeMap::new(), }; + // Now we want to populate the CrateDefMap using the DefCollector errors.extend(DefCollector::collect( def_map, &mut context, program.clone().into_sorted(), root_file_id, + Vec::new(), // No macro processors )); } (program, context, errors) } pub(crate) fn get_program_errors(src: &str) -> Vec<(CompilationError, FileId)> { - let (_program, _context, errors) = get_program(src); - errors - .iter() - .filter(|(e, _f)| match e.clone() { - CompilationError::ParseError(parser_error) => !matches!( - parser_error.reason(), - Some(ParserErrorReason::ExperimentalFeature(_)) - ), - _ => true, - }) - .cloned() - .collect() + get_program(src).2 } #[test] @@ -457,7 +442,7 @@ mod test { }"; let errors = get_program_errors(src); assert!(!has_parser_error(&errors)); - assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); + assert!(errors.len() == 2, "Expected 2 errors, got: {:?}", errors); for (err, _file_id) in errors { match &err { diff --git a/compiler/noirc_printable_type/src/lib.rs b/compiler/noirc_printable_type/src/lib.rs index 348f5ef327..e10e400b0d 100644 --- a/compiler/noirc_printable_type/src/lib.rs +++ b/compiler/noirc_printable_type/src/lib.rs @@ -168,15 +168,24 @@ fn fetch_printable_type( fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { let mut output = String::new(); match (value, typ) { - ( - PrintableValue::Field(f), - PrintableType::Field - // TODO(#2401): We should print the sign for these and probably print normal integers instead of field strings - | PrintableType::SignedInteger { .. } - | PrintableType::UnsignedInteger { .. }, - ) => { + (PrintableValue::Field(f), PrintableType::Field) => { output.push_str(&format_field_string(*f)); } + (PrintableValue::Field(f), PrintableType::UnsignedInteger { width }) => { + let uint_cast = f.to_u128() & ((1 << width) - 1); // Retain the lower 'width' bits + output.push_str(&uint_cast.to_string()); + } + (PrintableValue::Field(f), PrintableType::SignedInteger { width }) => { + let mut uint = f.to_u128(); // Interpret as uint + + // Extract sign relative to width of input + if (uint >> (width - 1)) == 1 { + output.push('-'); + uint = (uint ^ ((1 << width) - 1)) + 1; // Two's complement relative to width of input + } + + output.push_str(&uint.to_string()); + } (PrintableValue::Field(f), PrintableType::Boolean) => { if f.is_one() { output.push_str("true"); @@ -187,8 +196,11 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { (PrintableValue::Vec(vector), PrintableType::Array { typ, .. }) => { output.push('['); let mut values = vector.iter().peekable(); - while let Some(value) = values.next() { - output.push_str(&format!("{}", PrintableValueDisplay::Plain(value.clone(), *typ.clone()))); + while let Some(value) = values.next() { + output.push_str(&format!( + "{}", + PrintableValueDisplay::Plain(value.clone(), *typ.clone()) + )); if values.peek().is_some() { output.push_str(", "); } @@ -197,16 +209,19 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { } (PrintableValue::String(s), PrintableType::String { .. }) => { - output.push_str(&format!(r#""{s}""#)); + output.push_str(s); } (PrintableValue::Struct(map), PrintableType::Struct { name, fields, .. }) => { output.push_str(&format!("{name} {{ ")); let mut fields = fields.iter().peekable(); - while let Some((key, field_type)) = fields.next() { + while let Some((key, field_type)) = fields.next() { let value = &map[key]; - output.push_str(&format!("{key}: {}", PrintableValueDisplay::Plain(value.clone(), field_type.clone()))); + output.push_str(&format!( + "{key}: {}", + PrintableValueDisplay::Plain(value.clone(), field_type.clone()) + )); if fields.peek().is_some() { output.push_str(", "); } @@ -215,7 +230,7 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { output.push_str(" }"); } - _ => return None + _ => return None, }; Some(output) diff --git a/compiler/source-resolver/.eslintignore b/compiler/source-resolver/.eslintignore deleted file mode 100644 index 3c3629e647..0000000000 --- a/compiler/source-resolver/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/compiler/source-resolver/.eslintrc.js b/compiler/source-resolver/.eslintrc.js deleted file mode 100644 index 33335c2a87..0000000000 --- a/compiler/source-resolver/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ["../../.eslintrc.js"], -}; diff --git a/compiler/source-resolver/package.json b/compiler/source-resolver/package.json deleted file mode 100644 index fb214a822e..0000000000 --- a/compiler/source-resolver/package.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "@noir-lang/source-resolver", - "version": "0.19.2", - "license": "MIT", - "main": "./lib-node/index_node.js", - "types": "./types/index_node.d.ts", - "module": "./lib/index.js", - "browser": "./lib/index.js", - "exports": { - ".": { - "require": "./lib-node/index_node.js", - "import": "./lib/index.js" - } - }, - "repository": { - "type": "git", - "url": "https://github.com/noir-lang/noir.git" - }, - "scripts": { - "clean-modules": "rm -rf lib", - "build:node": "tsc -p tsconfig.cjs.json", - "build:web": "tsc -p tsconfig.esm.json", - "build": "npm run clean-modules && npm run build:node && npm run build:web && npm run generate-types", - "test": "ava", - "generate-types": "tsc src/*.ts --declaration --emitDeclarationOnly --outDir types", - "clean": "rm -rf ./lib ./lib-node", - "nightly:version": "jq --arg new_version \"-$(git rev-parse --short HEAD)$1\" '.version = .version + $new_version' package.json > package-tmp.json && mv package-tmp.json package.json", - "publish": "echo 📡 publishing `$npm_package_name` && yarn npm publish", - "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" - }, - "devDependencies": { - "@types/node": "^20.5.7", - "ava": "^5.2.0", - "typescript": "4.9.4" - }, - "files": [ - "lib", - "lib-node", - "src", - "types", - "package.json" - ] -} diff --git a/compiler/source-resolver/src/index.ts b/compiler/source-resolver/src/index.ts deleted file mode 100644 index 3498c195fb..0000000000 --- a/compiler/source-resolver/src/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -let resolveFunction: ((source_id: string) => string) | null = null; - -export const read_file = function (source_id: string): string { - if (resolveFunction) { - const result = resolveFunction(source_id); - - if (typeof result === 'string') { - return result; - } else { - throw new Error( - 'Noir source resolver function MUST return String synchronously. Are you trying to return anything else, eg. `Promise`?', - ); - } - } else { - throw new Error('Not yet initialized. Use initializeResolver(() => string)'); - } -}; - -function initialize(noir_resolver: (source_id: string) => string): (source_id: string) => string { - if (typeof noir_resolver === 'function') { - return noir_resolver; - } else { - throw new Error( - 'Provided Noir Resolver is not a function, hint: use function(module_id) => NoirSource as second parameter', - ); - } -} - -export function initializeResolver(resolver: (source_id: string) => string): void { - resolveFunction = initialize(resolver); -} diff --git a/compiler/source-resolver/src/index_node.ts b/compiler/source-resolver/src/index_node.ts deleted file mode 100644 index 14b7efd30c..0000000000 --- a/compiler/source-resolver/src/index_node.ts +++ /dev/null @@ -1,17 +0,0 @@ -/// - -import { initializeResolver, read_file } from './index.js'; - -initializeResolver((source_id: string) => { - let fileContent = ''; - try { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const fs = require('fs'); - fileContent = fs.readFileSync(source_id, { encoding: 'utf8' }) as string; - } catch (e) { - console.log(e); - } - return fileContent; -}); - -export { initializeResolver, read_file }; diff --git a/compiler/source-resolver/test/cjs_initialization.test.cjs b/compiler/source-resolver/test/cjs_initialization.test.cjs deleted file mode 100644 index 1dc7784fa4..0000000000 --- a/compiler/source-resolver/test/cjs_initialization.test.cjs +++ /dev/null @@ -1,51 +0,0 @@ -const test = require('ava'); - -const { initializeResolver, read_file } = require("../lib-node/index_node.js"); - -test('It reads file from file system within read_file using default implementation.', t => { - - const readResult = read_file("./package.json"); - - t.assert(readResult, "return from `read_file` should by truthy"); - -}); - -test('It calls function from initializer within read_file function.', t => { - - const RESULT_RESPONSE = "TEST"; - - initializeResolver((source) => { - return source; - }); - - const readResult = read_file(RESULT_RESPONSE); - - t.is(readResult, RESULT_RESPONSE); - -}); - -test('It communicates error when resolver returns non-String to read_file function.', t => { - - const RESULT_RESPONSE = "TEST"; - - initializeResolver((source) => { - return Promise.resolve(source); - }); - - const error = t.throws(() => { - read_file(RESULT_RESPONSE); - }, { instanceOf: Error }); - - t.is(error.message, 'Noir source resolver function MUST return String synchronously. Are you trying to return anything else, eg. `Promise`?'); - -}); - -test('It communicates error when resolver is initialized to anything but a function.', t => { - - const error = t.throws(() => { - initializeResolver(null); - }, { instanceOf: Error }); - - t.is(error.message, 'Provided Noir Resolver is not a function, hint: use function(module_id) => NoirSource as second parameter'); - -}); diff --git a/compiler/source-resolver/test/esm_initialization.test.mjs b/compiler/source-resolver/test/esm_initialization.test.mjs deleted file mode 100644 index 197b48e48d..0000000000 --- a/compiler/source-resolver/test/esm_initialization.test.mjs +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Below tests are commented because they require - * "type": "module", in package.json - * Seems that both CJS and MJS modes are not going to work. -*/ -import test from 'ava'; - -import { initializeResolver, read_file } from "../lib-node/index.js"; - -test('It communicates error when read_file was called before initializeResolver.', t => { - - const error = t.throws(() => { - const readResult = read_file("./package.json"); - }, { instanceOf: Error }); - - t.is(error.message, 'Not yet initialized. Use initializeResolver(() => string)'); - -}); - -test('It calls function from initializer within read_file function.', t => { - - const RESULT_RESPONSE = "TEST"; - - initializeResolver((source) => { - return source; - }); - - const readResult = read_file(RESULT_RESPONSE); - - t.is(readResult, RESULT_RESPONSE); - -}); - -test('It communicates error when resolver returns non-String to read_file function.', t => { - - const RESULT_RESPONSE = "TEST"; - - initializeResolver((source) => { - return Promise.resolve(source); - }); - - const error = t.throws(() => { - read_file(RESULT_RESPONSE); - }, { instanceOf: Error }); - - t.is(error.message, 'Noir source resolver function MUST return String synchronously. Are you trying to return anything else, eg. `Promise`?'); - -}); - -test('It communicates error when resolver is initialized to anything but a function.', t => { - - const error = t.throws(() => { - initializeResolver(null); - }, { instanceOf: Error }); - - t.is(error.message, 'Provided Noir Resolver is not a function, hint: use function(module_id) => NoirSource as second parameter'); - -}); diff --git a/compiler/source-resolver/tsconfig.cjs.json b/compiler/source-resolver/tsconfig.cjs.json deleted file mode 100644 index 51863a34ce..0000000000 --- a/compiler/source-resolver/tsconfig.cjs.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "target": "es2018", - "moduleResolution": "node", - "outDir": "lib-node", - "module": "commonjs", - "strict": true, - "esModuleInterop": true, - "noImplicitAny": true, - "removeComments": false, - "preserveConstEnums": true, - "sourceMap": true, - "importHelpers": true - }, - "include": ["src"] -} diff --git a/compiler/source-resolver/tsconfig.esm.json b/compiler/source-resolver/tsconfig.esm.json deleted file mode 100644 index dcf4441c4a..0000000000 --- a/compiler/source-resolver/tsconfig.esm.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "target": "es2018", - "moduleResolution": "node", - "outDir": "lib", - "module": "ES6", - "strict": true, - "esModuleInterop": true, - "noImplicitAny": true, - "removeComments": false, - "preserveConstEnums": true, - "sourceMap": true, - "importHelpers": true - }, - "include": ["src/index.ts"] -} diff --git a/compiler/source-resolver/types/index.d.ts b/compiler/source-resolver/types/index.d.ts deleted file mode 100644 index a17f7bc36b..0000000000 --- a/compiler/source-resolver/types/index.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export declare const read_file: (source_id: string) => string; -export declare function initializeResolver(resolver: (source_id: string) => string): void; diff --git a/compiler/source-resolver/types/index_node.d.ts b/compiler/source-resolver/types/index_node.d.ts deleted file mode 100644 index 3a109e47e7..0000000000 --- a/compiler/source-resolver/types/index_node.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { initializeResolver, read_file } from './index.js'; -export { initializeResolver, read_file }; diff --git a/compiler/wasm/Cargo.toml b/compiler/wasm/Cargo.toml index 9ece26c6df..58ad7764fd 100644 --- a/compiler/wasm/Cargo.toml +++ b/compiler/wasm/Cargo.toml @@ -21,11 +21,10 @@ noirc_errors.workspace = true wasm-bindgen.workspace = true serde.workspace = true js-sys.workspace = true -cfg-if.workspace = true console_error_panic_hook.workspace = true gloo-utils.workspace = true +log.workspace = true -log = "0.4.17" wasm-logger = "0.2.0" # This is an unused dependency, we are adding it diff --git a/compiler/wasm/build.sh b/compiler/wasm/build.sh index 37f2fd0a5a..24af149bce 100755 --- a/compiler/wasm/build.sh +++ b/compiler/wasm/build.sh @@ -34,7 +34,7 @@ export CARGO_TARGET_DIR=$self_path/target rm -rf $self_path/outputs >/dev/null 2>&1 rm -rf $self_path/result >/dev/null 2>&1 -if [ -v out ]; then +if [ -n "$out" ]; then echo "Will install package to $out (defined outside installPhase.sh script)" else export out="$self_path/outputs/out" diff --git a/compiler/wasm/package.json b/compiler/wasm/package.json index 75b876e1db..b57f700b66 100644 --- a/compiler/wasm/package.json +++ b/compiler/wasm/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.19.2", + "version": "0.20.0", "license": "(MIT OR Apache-2.0)", "main": "./nodejs/noir_wasm.js", "types": "./web/noir_wasm.d.ts", @@ -30,9 +30,6 @@ "build:nix": "nix build -L .#noir_wasm", "install:from:nix": "yarn clean && yarn build:nix && cp -rL ./result/noir_wasm/nodejs ./ && cp -rL ./result/noir_wasm/web ./" }, - "peerDependencies": { - "@noir-lang/source-resolver": "workspace:*" - }, "devDependencies": { "@esm-bundle/chai": "^4.3.4-fix.0", "@web/dev-server-esbuild": "^0.3.6", diff --git a/compiler/wasm/src/compile.rs b/compiler/wasm/src/compile.rs index e7fd3dd521..13b366819b 100644 --- a/compiler/wasm/src/compile.rs +++ b/compiler/wasm/src/compile.rs @@ -126,6 +126,31 @@ struct DependencyGraph { library_dependencies: HashMap>, } +#[wasm_bindgen] +// This is a map containing the paths of all of the files in the entry-point crate and +// the transitive dependencies of the entry-point crate. +// +// This is for all intents and purposes the file system that the compiler will use to resolve/compile +// files in the crate being compiled and its dependencies. +#[derive(Deserialize, Default)] +pub struct PathToFileSourceMap(HashMap); + +#[wasm_bindgen] +impl PathToFileSourceMap { + #[wasm_bindgen(constructor)] + pub fn new() -> PathToFileSourceMap { + PathToFileSourceMap::default() + } + // Inserts a path and its source code into the map. + // + // Returns true, if there was already source code in the map for the given path + pub fn add_source_code(&mut self, path: String, source_code: String) -> bool { + let path_buf = Path::new(&path).to_path_buf(); + let old_value = self.0.insert(path_buf, source_code); + old_value.is_some() + } +} + pub enum CompileResult { Contract { contract: PreprocessedContract, debug: DebugArtifact }, Program { program: PreprocessedProgram, debug: DebugArtifact }, @@ -136,6 +161,7 @@ pub fn compile( entry_point: String, contracts: Option, dependency_graph: Option, + file_source_map: PathToFileSourceMap, ) -> Result { console_error_panic_hook::set_once(); @@ -146,8 +172,8 @@ pub fn compile( DependencyGraph { root_dependencies: vec![], library_dependencies: HashMap::new() } }; - let root = Path::new("/"); - let fm = FileManager::new(root, Box::new(get_non_stdlib_asset)); + let fm = file_manager_with_source_map(file_source_map); + let graph = CrateGraph::default(); let mut context = Context::new(fm, graph); @@ -200,6 +226,31 @@ pub fn compile( } } +// Create a new FileManager with the given source map +// +// Note: Use this method whenever initializing a new FileManager +// to ensure that the file manager contains all of the files +// that one intends the compiler to use. +// +// For all intents and purposes, the file manager being returned +// should be considered as immutable. +fn file_manager_with_source_map(source_map: PathToFileSourceMap) -> FileManager { + let root = Path::new(""); + let mut fm = FileManager::new(root); + + for (path, source) in source_map.0 { + fm.add_file_with_source(path.as_path(), source); + } + + fm +} + +// Root dependencies are dependencies which the entry-point package relies upon. +// These will be in the Nargo.toml of the package being compiled. +// +// Library dependencies are transitive dependencies; for example, if the entry-point relies +// upon some library `lib1`. Then the packages that `lib1` depend upon will be placed in the +// `library_dependencies` list and the `lib1` will be placed in the `root_dependencies` list. fn process_dependency_graph(context: &mut Context, dependency_graph: DependencyGraph) { let mut crate_names: HashMap<&CrateName, CrateId> = HashMap::new(); @@ -279,51 +330,26 @@ fn preprocess_contract(contract: CompiledContract) -> CompileResult { CompileResult::Contract { contract: preprocessed_contract, debug: debug_artifact } } -cfg_if::cfg_if! { - if #[cfg(target_os = "wasi")] { - fn get_non_stdlib_asset(path_to_file: &Path) -> std::io::Result { - std::fs::read_to_string(path_to_file) - } - } else { - use std::io::{Error, ErrorKind}; - - #[wasm_bindgen(module = "@noir-lang/source-resolver")] - extern "C" { - #[wasm_bindgen(catch)] - fn read_file(path: &str) -> Result; - } - - fn get_non_stdlib_asset(path_to_file: &Path) -> std::io::Result { - let path_str = path_to_file.to_str().unwrap(); - match read_file(path_str) { - Ok(buffer) => Ok(buffer), - Err(_) => Err(Error::new(ErrorKind::Other, "could not read file using wasm")), - } - } - } -} - #[cfg(test)] mod test { - use fm::FileManager; use noirc_driver::prepare_crate; use noirc_frontend::{ graph::{CrateGraph, CrateName}, hir::Context, }; - use super::{process_dependency_graph, DependencyGraph}; + use crate::compile::PathToFileSourceMap; + + use super::{file_manager_with_source_map, process_dependency_graph, DependencyGraph}; use std::{collections::HashMap, path::Path}; - fn mock_get_non_stdlib_asset(_path_to_file: &Path) -> std::io::Result { - Ok("".to_string()) - } + fn setup_test_context(source_map: PathToFileSourceMap) -> Context { + let mut fm = file_manager_with_source_map(source_map); + // Add this due to us calling prepare_crate on "/main.nr" below + fm.add_file_with_source(Path::new("/main.nr"), "fn foo() {}".to_string()); - fn setup_test_context() -> Context { - let fm = FileManager::new(Path::new("/"), Box::new(mock_get_non_stdlib_asset)); let graph = CrateGraph::default(); let mut context = Context::new(fm, graph); - prepare_crate(&mut context, Path::new("/main.nr")); context @@ -335,10 +361,12 @@ mod test { #[test] fn test_works_with_empty_dependency_graph() { - let mut context = setup_test_context(); let dependency_graph = DependencyGraph { root_dependencies: vec![], library_dependencies: HashMap::new() }; + let source_map = PathToFileSourceMap::default(); + let mut context = setup_test_context(source_map); + process_dependency_graph(&mut context, dependency_graph); // one stdlib + one root crate @@ -347,12 +375,19 @@ mod test { #[test] fn test_works_with_root_dependencies() { - let mut context = setup_test_context(); let dependency_graph = DependencyGraph { root_dependencies: vec![crate_name("lib1")], library_dependencies: HashMap::new(), }; + let source_map = PathToFileSourceMap( + vec![(Path::new("lib1/lib.nr").to_path_buf(), "fn foo() {}".to_string())] + .into_iter() + .collect(), + ); + + let mut context = setup_test_context(source_map); + process_dependency_graph(&mut context, dependency_graph); assert_eq!(context.crate_graph.number_of_crates(), 3); @@ -360,12 +395,18 @@ mod test { #[test] fn test_works_with_duplicate_root_dependencies() { - let mut context = setup_test_context(); let dependency_graph = DependencyGraph { root_dependencies: vec![crate_name("lib1"), crate_name("lib1")], library_dependencies: HashMap::new(), }; + let source_map = PathToFileSourceMap( + vec![(Path::new("lib1/lib.nr").to_path_buf(), "fn foo() {}".to_string())] + .into_iter() + .collect(), + ); + let mut context = setup_test_context(source_map); + process_dependency_graph(&mut context, dependency_graph); assert_eq!(context.crate_graph.number_of_crates(), 3); @@ -373,7 +414,6 @@ mod test { #[test] fn test_works_with_transitive_dependencies() { - let mut context = setup_test_context(); let dependency_graph = DependencyGraph { root_dependencies: vec![crate_name("lib1")], library_dependencies: HashMap::from([ @@ -382,6 +422,17 @@ mod test { ]), }; + let source_map = PathToFileSourceMap( + vec![ + (Path::new("lib1/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + (Path::new("lib2/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + (Path::new("lib3/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + ] + .into_iter() + .collect(), + ); + + let mut context = setup_test_context(source_map); process_dependency_graph(&mut context, dependency_graph); assert_eq!(context.crate_graph.number_of_crates(), 5); @@ -389,12 +440,22 @@ mod test { #[test] fn test_works_with_missing_dependencies() { - let mut context = setup_test_context(); let dependency_graph = DependencyGraph { root_dependencies: vec![crate_name("lib1")], library_dependencies: HashMap::from([(crate_name("lib2"), vec![crate_name("lib3")])]), }; + let source_map = PathToFileSourceMap( + vec![ + (Path::new("lib1/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + (Path::new("lib2/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + (Path::new("lib3/lib.nr").to_path_buf(), "fn foo() {}".to_string()), + ] + .into_iter() + .collect(), + ); + + let mut context = setup_test_context(source_map); process_dependency_graph(&mut context, dependency_graph); assert_eq!(context.crate_graph.number_of_crates(), 5); diff --git a/compiler/wasm/test/browser/index.test.ts b/compiler/wasm/test/browser/index.test.ts index 8a3f82ffff..346c20c834 100644 --- a/compiler/wasm/test/browser/index.test.ts +++ b/compiler/wasm/test/browser/index.test.ts @@ -1,6 +1,5 @@ import { expect } from '@esm-bundle/chai'; -import initNoirWasm, { compile } from '@noir-lang/noir_wasm'; -import { initializeResolver } from '@noir-lang/source-resolver'; +import initNoirWasm, { PathToFileSourceMap, compile } from '@noir-lang/noir_wasm'; import { depsScriptExpectedArtifact, depsScriptSourcePath, @@ -28,23 +27,11 @@ async function getPrecompiledSource(path: string): Promise { describe('noir wasm', () => { describe('can compile script without dependencies', () => { - beforeEach(async () => { - const source = await getFileContent(simpleScriptSourcePath); - initializeResolver((id: string) => { - console.log(`Resolving source ${id}`); - - if (typeof source === 'undefined') { - throw Error(`Could not resolve source for '${id}'`); - } else if (id !== '/main.nr') { - throw Error(`Unexpected id: '${id}'`); - } else { - return source; - } - }); - }); - it('matching nargos compilation', async () => { - const wasmCircuit = await compile('/main.nr'); + const sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code('main.nr', await getFileContent(simpleScriptSourcePath)); + + const wasmCircuit = await compile('main.nr', undefined, undefined, sourceMap); const cliCircuit = await getPrecompiledSource(simpleScriptExpectedArtifact); if (!('program' in wasmCircuit)) { @@ -59,37 +46,29 @@ describe('noir wasm', () => { }); describe('can compile script with dependencies', () => { - beforeEach(async () => { + it('matching nargos compilation', async () => { const [scriptSource, libASource, libBSource] = await Promise.all([ getFileContent(depsScriptSourcePath), getFileContent(libASourcePath), getFileContent(libBSourcePath), ]); - initializeResolver((file: string) => { - switch (file) { - case '/script/main.nr': - return scriptSource; - - case '/lib_a/lib.nr': - return libASource; - - case '/lib_b/lib.nr': - return libBSource; - - default: - return ''; - } - }); - }); - - it('matching nargos compilation', async () => { - const wasmCircuit = await compile('/script/main.nr', false, { - root_dependencies: ['lib_a'], - library_dependencies: { - lib_a: ['lib_b'], + const sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code('script/main.nr', scriptSource); + sourceMap.add_source_code('lib_a/lib.nr', libASource); + sourceMap.add_source_code('lib_b/lib.nr', libBSource); + + const wasmCircuit = await compile( + 'script/main.nr', + false, + { + root_dependencies: ['lib_a'], + library_dependencies: { + lib_a: ['lib_b'], + }, }, - }); + sourceMap, + ); if (!('program' in wasmCircuit)) { throw Error('Expected program to be present'); diff --git a/compiler/wasm/test/node/index.test.ts b/compiler/wasm/test/node/index.test.ts index c0d5f88e40..5cf9e3be2d 100644 --- a/compiler/wasm/test/node/index.test.ts +++ b/compiler/wasm/test/node/index.test.ts @@ -9,8 +9,7 @@ import { } from '../shared'; import { readFileSync } from 'node:fs'; import { join, resolve } from 'node:path'; -import { compile } from '@noir-lang/noir_wasm'; -import { initializeResolver } from '@noir-lang/source-resolver'; +import { compile, PathToFileSourceMap } from '@noir-lang/noir_wasm'; // eslint-disable-next-line @typescript-eslint/no-explicit-any async function getPrecompiledSource(path: string): Promise { @@ -21,7 +20,12 @@ async function getPrecompiledSource(path: string): Promise { describe('noir wasm compilation', () => { describe('can compile simple scripts', () => { it('matching nargos compilation', async () => { - const wasmCircuit = await compile(join(__dirname, simpleScriptSourcePath)); + const sourceMap = new PathToFileSourceMap(); + sourceMap.add_source_code( + join(__dirname, simpleScriptSourcePath), + readFileSync(join(__dirname, simpleScriptSourcePath), 'utf-8'), + ); + const wasmCircuit = await compile(join(__dirname, simpleScriptSourcePath), undefined, undefined, sourceMap); const cliCircuit = await getPrecompiledSource(simpleScriptExpectedArtifact); if (!('program' in wasmCircuit)) { @@ -36,32 +40,25 @@ describe('noir wasm compilation', () => { }); describe('can compile scripts with dependencies', () => { + const sourceMap: PathToFileSourceMap = new PathToFileSourceMap(); beforeEach(() => { - // this test requires a custom resolver in order to correctly resolve dependencies - initializeResolver((file) => { - switch (file) { - case '/script/main.nr': - return readFileSync(join(__dirname, depsScriptSourcePath), 'utf-8'); - - case '/lib_a/lib.nr': - return readFileSync(join(__dirname, libASourcePath), 'utf-8'); - - case '/lib_b/lib.nr': - return readFileSync(join(__dirname, libBSourcePath), 'utf-8'); - - default: - return ''; - } - }); + sourceMap.add_source_code('script/main.nr', readFileSync(join(__dirname, depsScriptSourcePath), 'utf-8')); + sourceMap.add_source_code('lib_a/lib.nr', readFileSync(join(__dirname, libASourcePath), 'utf-8')); + sourceMap.add_source_code('lib_b/lib.nr', readFileSync(join(__dirname, libBSourcePath), 'utf-8')); }); it('matching nargos compilation', async () => { - const wasmCircuit = await compile('/script/main.nr', false, { - root_dependencies: ['lib_a'], - library_dependencies: { - lib_a: ['lib_b'], + const wasmCircuit = await compile( + 'script/main.nr', + false, + { + root_dependencies: ['lib_a'], + library_dependencies: { + lib_a: ['lib_b'], + }, }, - }); + sourceMap, + ); const cliCircuit = await getPrecompiledSource(depsScriptExpectedArtifact); diff --git a/cspell.json b/cspell.json index 90d3963566..e02e68871b 100644 --- a/cspell.json +++ b/cspell.json @@ -5,6 +5,7 @@ "acir", "acvm", "aeiou", + "appender", "arithmetization", "arity", "arkworks", @@ -79,15 +80,18 @@ "monomorphizes", "nand", "nargo", + "newtype", "nixpkgs", "noirc", "noirup", + "nomicfoundation", "pedersen", "peekable", "plonkc", "pprof", "preprocess", "prettytable", + "println", "printstd", "pseudocode", "quantile", diff --git a/docs/.eslintignore b/docs/.eslintignore new file mode 100644 index 0000000000..dd87e2d73f --- /dev/null +++ b/docs/.eslintignore @@ -0,0 +1,2 @@ +node_modules +build diff --git a/docs/.gitignore b/docs/.gitignore index e76d8caf6b..e4abc8785c 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -7,7 +7,7 @@ # Generated files .docusaurus .cache-loader -/docs/noir_js/reference/ +/docs/docs/reference/NoirJS # Misc .DS_Store @@ -21,4 +21,4 @@ npm-debug.log* yarn-debug.log* yarn-error.log* -package-lock.json \ No newline at end of file +package-lock.json diff --git a/docs/.prettierrc b/docs/.prettierrc deleted file mode 100644 index 6031f40b26..0000000000 --- a/docs/.prettierrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "arrowParens": "avoid", - "singleQuote": true, - "trailingComma": "all", - "printWidth": 100 -} diff --git a/docs/babel.config.js b/docs/babel.config.js deleted file mode 100644 index e00595dae7..0000000000 --- a/docs/babel.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - presets: [require.resolve('@docusaurus/core/lib/babel/preset')], -}; diff --git a/docs/docs/explanations/_category_.json b/docs/docs/explanations/_category_.json new file mode 100644 index 0000000000..151ee20489 --- /dev/null +++ b/docs/docs/explanations/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 3, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/explanations/modules_packages_crates/_category_.json b/docs/docs/explanations/modules_packages_crates/_category_.json new file mode 100644 index 0000000000..1debcfe767 --- /dev/null +++ b/docs/docs/explanations/modules_packages_crates/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Modules, Packages and Crates", + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/explanations/modules_packages_crates/crates_and_packages.md b/docs/docs/explanations/modules_packages_crates/crates_and_packages.md new file mode 100644 index 0000000000..aae6795b22 --- /dev/null +++ b/docs/docs/explanations/modules_packages_crates/crates_and_packages.md @@ -0,0 +1,43 @@ +--- +title: Crates and Packages +description: Learn how to use Crates and Packages in your Noir project +keywords: [Nargo, dependencies, package management, crates, package] +sidebar_position: 0 +--- + +## Crates + +A crate is the smallest amount of code that the Noir compiler considers at a time. +Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. + +### Crate Types + +A Noir crate can come in several forms: binaries, libraries or contracts. + +#### Binaries + +_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. + +#### Libraries + +_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. + +#### Contracts + +Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-contracts/src/contracts). + +### Crate Root + +Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. + +## Packages + +A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. + +A package _must_ contain either a library or a binary crate, but not both. + +### Differences from Cargo Packages + +One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. + +In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/docs/docs/explanations/modules_packages_crates/dependencies.md b/docs/docs/explanations/modules_packages_crates/dependencies.md new file mode 100644 index 0000000000..57f0f9fd42 --- /dev/null +++ b/docs/docs/explanations/modules_packages_crates/dependencies.md @@ -0,0 +1,124 @@ +--- +title: Dependencies +description: + Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub + and use them easily in your project. +keywords: [Nargo, dependencies, GitHub, package management, versioning] +sidebar_position: 1 +--- + +Nargo allows you to upload packages to GitHub and use them as dependencies. + +## Specifying a dependency + +Specifying a dependency requires a tag to a specific commit and the git url to the url containing +the package. + +Currently, there are no requirements on the tag contents. If requirements are added, it would follow +semver 2.0 guidelines. + +> Note: Without a `tag` , there would be no versioning and dependencies would change each time you +> compile your project. + +For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: + +```toml +# Nargo.toml + +[dependencies] +ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} +``` + +If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: + +```toml +# Nargo.toml + +[dependencies] +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/src/contracts/easy_private_token_contract"} +``` + +## Specifying a local dependency + +You can also specify dependencies that are local to your machine. + +For example, this file structure has a library and binary crate + +```tree +├── binary_crate +│   ├── Nargo.toml +│   └── src +│   └── main.nr +└── liba + ├── Nargo.toml + └── src + └── lib.nr +``` + +Inside of the binary crate, you can specify: + +```toml +# Nargo.toml + +[dependencies] +libA = { path = "../liba" } +``` + +## Importing dependencies + +You can import a dependency to a Noir file using the following syntax. For example, to import the +ecrecover-noir library and local liba referenced above: + +```rust +use dep::ecrecover; +use dep::libA; +``` + +You can also import only the specific parts of dependency that you want to use, like so: + +```rust +use dep::std::hash::sha256; +use dep::std::scalar_mul::fixed_base_embedded_curve; +``` + +Lastly, as demonstrated in the +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +can import multiple items in the same line by enclosing them in curly braces: + +```rust +use dep::std::ec::tecurve::affine::{Curve, Point}; +``` + +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. + +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +## Dependencies of Dependencies + +Note that when you import a dependency, you also get access to all of the dependencies of that package. + +For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: + +```rust +use dep::phy_vector; + +fn main(x : Field, y : pub Field) { + //... + let f = phy_vector::fraction::toFraction(true, 2, 1); + //... +} +``` + +## Available Libraries + +Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). + +Some libraries that are available today include: + +- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library +- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) +- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers +- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address +- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees +- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir +- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/docs/docs/explanations/modules_packages_crates/modules.md b/docs/docs/explanations/modules_packages_crates/modules.md new file mode 100644 index 0000000000..f9f15aee8b --- /dev/null +++ b/docs/docs/explanations/modules_packages_crates/modules.md @@ -0,0 +1,105 @@ +--- +title: Modules +description: + Learn how to organize your files using modules in Noir, following the same convention as Rust's + module system. Examples included. +keywords: [Noir, Rust, modules, organizing files, sub-modules] +sidebar_position: 2 +--- + +Noir's module system follows the same convention as the _newer_ version of Rust's module system. + +## Purpose of Modules + +Modules are used to organise files. Without modules all of your code would need to live in a single +file. In Noir, the compiler does not automatically scan all of your files to detect modules. This +must be done explicitly by the developer. + +## Examples + +### Importing a module in the crate root + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::hello_world(); +} +``` + +Filename : `src/foo.nr` + +```rust +fn from_foo() {} +``` + +In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module +declaration `mod foo` which prompts it to look for a foo.nr file. + +Visually this module hierarchy looks like the following : + +``` +crate + ├── main + │ + └── foo + └── from_foo + +``` + +### Importing a module throughout the tree + +All modules are accessible from the `crate::` namespace. + +``` +crate + ├── bar + ├── foo + └── main + +``` + +In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. + +### Sub-modules + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::from_foo(); +} +``` + +Filename : `src/foo.nr` + +```rust +mod bar; +fn from_foo() {} +``` + +Filename : `src/foo/bar.nr` + +```rust +fn from_bar() {} +``` + +In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule +of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the +compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` + +Visually the module hierarchy looks as follows: + +``` +crate + ├── main + │ + └── foo + ├── from_foo + └── bar + └── from_bar +``` diff --git a/docs/docs/explanations/modules_packages_crates/workspaces.md b/docs/docs/explanations/modules_packages_crates/workspaces.md new file mode 100644 index 0000000000..67a1dafa37 --- /dev/null +++ b/docs/docs/explanations/modules_packages_crates/workspaces.md @@ -0,0 +1,40 @@ +--- +title: Workspaces +sidebar_position: 3 +--- + +Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. + +Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. + +For a project with the following structure: + +```tree +├── crates +│   ├── a +│   │   ├── Nargo.toml +│   │   └── src +│   │   └── main.nr +│   └── b +│   ├── Nargo.toml +│   └── src +│   └── main.nr +├── Nargo.toml +└── Prover.toml +``` + +You can define a workspace in Nargo.toml like so: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. + +`default-member` indicates which package various commands process by default. + +Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/docs/explanations/noir/_category_.json b/docs/docs/explanations/noir/_category_.json new file mode 100644 index 0000000000..448d8987d1 --- /dev/null +++ b/docs/docs/explanations/noir/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Noir", + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/explanations/noir/assert.md b/docs/docs/explanations/noir/assert.md new file mode 100644 index 0000000000..c5f9aff139 --- /dev/null +++ b/docs/docs/explanations/noir/assert.md @@ -0,0 +1,27 @@ +--- +title: Assert Function +description: + Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or + comparison expression that follows to be true, and what happens if the expression is false at + runtime. +keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +sidebar_position: 4 +--- + +Noir includes a special `assert` function which will explicitly constrain the predicate/comparison +expression that follows to be true. If this expression is false at runtime, the program will fail to +be proven. Example: + +```rust +fn main(x : Field, y : Field) { + assert(x == y); +} +``` + +You can optionally provide a message to be logged when the assertion fails: + +```rust +assert(x == y, "x and y are not equal"); +``` + +> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. diff --git a/docs/docs/explanations/noir/comments.md b/docs/docs/explanations/noir/comments.md new file mode 100644 index 0000000000..f76ab49094 --- /dev/null +++ b/docs/docs/explanations/noir/comments.md @@ -0,0 +1,33 @@ +--- +title: Comments +description: + Learn how to write comments in Noir programming language. A comment is a line of code that is + ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments + are supported in Noir. +keywords: [Noir programming language, comments, single-line comments, multi-line comments] +sidebar_position: 9 +--- + +A comment is a line in your codebase which the compiler ignores, however it can be read by +programmers. + +Here is a single line comment: + +```rust +// This is a comment and is ignored +``` + +`//` is used to tell the compiler to ignore the rest of the line. + +Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. + +Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. + +```rust +/* + This is a block comment describing a complex function. +*/ +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` diff --git a/docs/docs/explanations/noir/control_flow.md b/docs/docs/explanations/noir/control_flow.md new file mode 100644 index 0000000000..4ce65236db --- /dev/null +++ b/docs/docs/explanations/noir/control_flow.md @@ -0,0 +1,45 @@ +--- +title: Control Flow +description: + Learn how to use loops and if expressions in the Noir programming language. Discover the syntax + and examples for for loops and if-else statements. +keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +sidebar_position: 2 +--- + +## Loops + +Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple +times. + +The following block of code between the braces is run 10 times. + +```rust +for i in 0..10 { + // do something +}; +``` + +The index for loops is of type `u64`. + +## If Expressions + +Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required +for the statement's conditional to be surrounded by parentheses. + +```rust +let a = 0; +let mut x: u32 = 0; + +if a == 0 { + if a != 0 { + x = 6; + } else { + x = 2; + } +} else { + x = 5; + assert(x == 5); +} +assert(x == 2); +``` diff --git a/docs/docs/explanations/noir/data_bus.md b/docs/docs/explanations/noir/data_bus.md new file mode 100644 index 0000000000..6c7e9b6089 --- /dev/null +++ b/docs/docs/explanations/noir/data_bus.md @@ -0,0 +1,21 @@ +--- +title: Data Bus +sidebar_position: 12 +--- +**Disclaimer** this feature is experimental, do not use it! + +The data bus is an optimization that the backend can use to make recursion more efficient. +In order to use it, you must define some inputs of the program entry points (usually the `main()` +function) with the `call_data` modifier, and the return values with the `return_data` modifier. +These modifiers are incompatible with `pub` and `mut` modifiers. + +## Example + +```rust +fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { + let a = z[x]; + a+y +} +``` + +As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/docs/docs/explanations/noir/data_types/_category_.json b/docs/docs/explanations/noir/data_types/_category_.json new file mode 100644 index 0000000000..5d694210bb --- /dev/null +++ b/docs/docs/explanations/noir/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/explanations/noir/data_types/arrays.md b/docs/docs/explanations/noir/data_types/arrays.md new file mode 100644 index 0000000000..075d39dadd --- /dev/null +++ b/docs/docs/explanations/noir/data_types/arrays.md @@ -0,0 +1,245 @@ +--- +title: Arrays +description: + Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. +keywords: + [ + noir, + array type, + methods, + examples, + indexing, + ] +sidebar_position: 4 +--- + +An array is one way of grouping together values into one compound type. Array types can be inferred +or explicitly specified via the syntax `[; ]`: + +```rust +fn main(x : Field, y : Field) { + let my_arr = [x, y]; + let your_arr: [Field; 2] = [x, y]; +} +``` + +Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. + +Array elements can be accessed using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group +a `Field` value and a `u8` value together for example. + +You can write mutable arrays, like: + +```rust +fn main() { + let mut arr = [1, 2, 3, 4, 5]; + assert(arr[0] == 1); + + arr[0] = 42; + assert(arr[0] == 42); +} +``` + +You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. + +```rust +let array: [Field; 32] = [0; 32]; +``` + +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: + +```rust +let array: [Field; 32] = [0; 32]; +let sl = array.as_slice() +``` + +You can define multidimensional arrays: + +```rust +let array : [[Field; 2]; 2]; +let element = array[0][0]; +``` + +## Types + +You can create arrays of primitive types or structs. There is not yet support for nested arrays +(arrays of arrays) or arrays of structs that contain arrays. + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for arrays: + +### len + +Returns the length of an array + +```rust +fn len(_array: [T; N]) -> comptime Field +``` + +example + +```rust +fn main() { + let array = [42, 42]; + assert(array.len() == 2); +} +``` + +### sort + +Returns a new sorted array. The original array remains untouched. Notice that this function will +only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting +logic it uses internally is optimized specifically for these values. If you need a sort function to +sort any type, you should use the function `sort_via` described below. + +```rust +fn sort(_array: [T; N]) -> [T; N] +``` + +example + +```rust +fn main() { + let arr = [42, 32]; + let sorted = arr.sort(); + assert(sorted == [32, 42]); +} +``` + +### sort_via + +Sorts the array with a custom comparison function + +```rust +fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] +``` + +example + +```rust +fn main() { + let arr = [42, 32] + let sorted_ascending = arr.sort_via(|a, b| a < b); + assert(sorted_ascending == [32, 42]); // verifies + + let sorted_descending = arr.sort_via(|a, b| a > b); + assert(sorted_descending == [32, 42]); // does not verify +} +``` + +### map + +Applies a function to each element of the array, returning a new array containing the mapped elements. + +```rust +fn map(f: fn(T) -> U) -> [U; N] +``` + +example + +```rust +let a = [1, 2, 3]; +let b = a.map(|a| a * 2); // b is now [2, 4, 6] +``` + +### fold + +Applies a function to each element of the array, returning the final accumulated value. The first +parameter is the initial value. + +```rust +fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U +``` + +This is a left fold, so the given function will be applied to the accumulator and first element of +the array, then the second, and so on. For a given call the expected result would be equivalent to: + +```rust +let a1 = [1]; +let a2 = [1, 2]; +let a3 = [1, 2, 3]; + +let f = |a, b| a - b; +a1.fold(10, f) //=> f(10, 1) +a2.fold(10, f) //=> f(f(10, 1), 2) +a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) +``` + +example: + +```rust + +fn main() { + let arr = [2, 2, 2, 2, 2]; + let folded = arr.fold(0, |a, b| a + b); + assert(folded == 10); +} + +``` + +### reduce + +Same as fold, but uses the first element as starting element. + +```rust +fn reduce(f: fn(T, T) -> T) -> T +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 2]; + let reduced = arr.reduce(|a, b| a + b); + assert(reduced == 10); +} +``` + +### all + +Returns true if all the elements satisfy the given predicate + +```rust +fn all(predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 2]; + let all = arr.all(|a| a == 2); + assert(all); +} +``` + +### any + +Returns true if any of the elements satisfy the given predicate + +```rust +fn any(predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 5]; + let any = arr.any(|a| a == 5); + assert(any); +} + +``` diff --git a/docs/docs/explanations/noir/data_types/booleans.md b/docs/docs/explanations/noir/data_types/booleans.md new file mode 100644 index 0000000000..69826fcd72 --- /dev/null +++ b/docs/docs/explanations/noir/data_types/booleans.md @@ -0,0 +1,31 @@ +--- +title: Booleans +description: + Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. +keywords: + [ + noir, + boolean type, + methods, + examples, + logical operations, + ] +sidebar_position: 2 +--- + + +The `bool` type in Noir has two possible values: `true` and `false`: + +```rust +fn main() { + let t = true; + let f: bool = false; +} +``` + +> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for +> `false` in _Verifier.toml_. + +The boolean type is most commonly used in conditionals like `if` expressions and `assert` +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/docs/explanations/noir/data_types/fields.md b/docs/docs/explanations/noir/data_types/fields.md new file mode 100644 index 0000000000..a1c67945d6 --- /dev/null +++ b/docs/docs/explanations/noir/data_types/fields.md @@ -0,0 +1,166 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +sidebar_position: 0 +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_le_bits(32); +} +``` + +### to_be_bits + +Transforms the field into an array of bits, Big Endian. + +```rust +fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_be_bits(32); +} +``` + +### to_le_bytes + +Transforms into an array of bytes, Little Endian + +```rust +fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_le_bytes(4); +} +``` + +### to_be_bytes + +Transforms into an array of bytes, Big Endian + +```rust +fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_be_bytes(4); +} +``` + +### to_le_radix + +Decomposes into a vector over the specified base, Little Endian + +```rust +fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_le_radix(256, 4); +} +``` + +### to_be_radix + +Decomposes into a vector over the specified base, Big Endian + +```rust +fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_be_radix(256, 4); +} +``` + +### pow_32 + +Returns the value to the power of the specified exponent + +```rust +fn pow_32(self, exponent: Field) -> Field +``` + +example: + +```rust +fn main() { + let field = 2 + let pow = field.pow_32(4); + assert(pow == 16); +} +``` + +### sgn0 + +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. + +```rust +fn sgn0(self) -> u1 +``` diff --git a/docs/docs/explanations/noir/data_types/function_types.md b/docs/docs/explanations/noir/data_types/function_types.md new file mode 100644 index 0000000000..f6121af17e --- /dev/null +++ b/docs/docs/explanations/noir/data_types/function_types.md @@ -0,0 +1,26 @@ +--- +title: Function types +sidebar_position: 10 +--- + +Noir supports higher-order functions. The syntax for a function type is as follows: + +```rust +fn(arg1_type, arg2_type, ...) -> return_type +``` + +Example: + +```rust +fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field + assert(f() == 100); +} + +fn main() { + assert_returns_100(|| 100); // ok + assert_returns_100(|| 150); // fails +} +``` + +A function type also has an optional capture environment - this is necessary to support closures. +See [Lambdas](../lambdas.md) for more details. diff --git a/docs/docs/explanations/noir/data_types/index.md b/docs/docs/explanations/noir/data_types/index.md new file mode 100644 index 0000000000..56ed55c444 --- /dev/null +++ b/docs/docs/explanations/noir/data_types/index.md @@ -0,0 +1,96 @@ +--- +title: Data Types +description: + Get a clear understanding of the two categories of Noir data types - primitive types and compound + types. Learn about their characteristics, differences, and how to use them in your Noir + programming. +keywords: + [ + noir, + data types, + primitive types, + compound types, + private types, + public types, + ] +--- + +Every value in Noir has a type, which determines which operations are valid for it. + +All values in Noir are fundamentally composed of `Field` elements. For a more approachable +developing experience, abstractions are added on top to introduce different data types in Noir. + +Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound +types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or +public. + +## Private & Public Types + +A **private value** is known only to the Prover, while a **public value** is known by both the +Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All +primitive types (including individual fields of compound types) in Noir are private by default, and +can be marked public when certain values are intended to be revealed to the Verifier. + +> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once +> the proofs are verified on-chain the values can be considered known to everyone that has access to +> that blockchain. + +Public data types are treated no differently to private types apart from the fact that their values +will be revealed in proofs generated. Simply changing the value of a public type will not change the +circuit (where the same goes for changing values of private types as well). + +_Private values_ are also referred to as _witnesses_ sometimes. + +> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different +> meaning than when applied to a function (e.g. `pub fn foo() {}`). +> +> The former is a visibility modifier for the Prover to interpret if a value should be made known to +> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a +> function should be made accessible to external Noir programs like in other languages. + +### pub Modifier + +All data types in Noir are private by default. Types are explicitly declared as public using the +`pub` modifier: + +```rust +fn main(x : Field, y : pub Field) -> pub Field { + x + y +} +``` + +In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note +that visibility is handled **per variable**, so it is perfectly valid to have one input that is +private and another that is public. + +> **Note:** Public types can only be declared through parameters on `main`. + +## Type Aliases + +A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: + +```rust +type Id = u8; + +fn main() { + let id: Id = 1; + let zero: u8 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can also be used with [generics](@site/docs/explanations/noir/generics.md): + +```rust +type Id = Size; + +fn main() { + let id: Id = 1; + let zero: u32 = 0; + assert(zero + 1 == id); +} +``` + +### BigInt + +You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/docs/explanations/noir/data_types/integers.md b/docs/docs/explanations/noir/data_types/integers.md new file mode 100644 index 0000000000..7d1e83cf4e --- /dev/null +++ b/docs/docs/explanations/noir/data_types/integers.md @@ -0,0 +1,113 @@ +--- +title: Integers +description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. +keywords: [noir, integer types, methods, examples, arithmetic] +sidebar_position: 1 +--- + +An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. + +:::info + +When an integer is defined in Noir without a specific type, it will default to `Field`. + +The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. + +::: + +## Unsigned Integers + +An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): + +```rust +fn main() { + let x: u8 = 1; + let y: u8 = 1; + let z = x + y; + assert (z == 2); +} +``` + +The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). + +## Signed Integers + +A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): + +```rust +fn main() { + let x: i8 = -1; + let y: i8 = -1; + let z = x + y; + assert (z == -2); +} +``` + +The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). + +:::tip + +If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. + +::: + +## Overflows + +Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: + +```rust +fn main(x: u8, y: u8) { + let z = x + y; +} +``` + +With: + +```toml +x = "255" +y = "1" +``` + +Would result in: + +``` +$ nargo prove +error: Assertion failed: 'attempt to add with overflow' +┌─ ~/src/main.nr:9:13 +│ +│ let z = x + y; +│ ----- +│ += Call stack: + ... +``` + +A similar error would happen with signed integers: + +```rust +fn main() { + let x: i8 = -118; + let y: i8 = -11; + let z = x + y; +} +``` + +### Wrapping methods + +Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: + +```rust +fn wrapping_add(x: T, y: T) -> T; +fn wrapping_sub(x: T, y: T) -> T; +fn wrapping_mul(x: T, y: T) -> T; +``` + +Example of how it is used: + +```rust +use dep::std; + +fn main(x: u8, y: u8) -> pub u8 { + std::wrapping_add(x + y) +} +``` diff --git a/docs/docs/explanations/noir/data_types/references.md b/docs/docs/explanations/noir/data_types/references.md new file mode 100644 index 0000000000..a5293d11cf --- /dev/null +++ b/docs/docs/explanations/noir/data_types/references.md @@ -0,0 +1,23 @@ +--- +title: References +sidebar_position: 9 +--- + +Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. + +Example: + +```rust +fn main() { + let mut x = 2; + + // you can reference x as &mut and pass it to multiplyBy2 + multiplyBy2(&mut x); +} + +// you can access &mut here +fn multiplyBy2(x: &mut Field) { + // and dereference it with * + *x = *x * 2; +} +``` diff --git a/docs/docs/explanations/noir/data_types/slices.mdx b/docs/docs/explanations/noir/data_types/slices.mdx new file mode 100644 index 0000000000..4a6ee816aa --- /dev/null +++ b/docs/docs/explanations/noir/data_types/slices.mdx @@ -0,0 +1,147 @@ +--- +title: Slices +description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. +keywords: [noir, slice type, methods, examples, subarrays] +sidebar_position: 5 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. + +```rust +use dep::std::slice; + +fn main() -> pub Field { + let mut slice: [Field] = [0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for slices: + +### push_back + +Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. + +```rust +fn push_back(_self: [T], _elem: T) -> [T] +``` + +example: + +```rust +fn main() -> pub Field { + let mut slice: [Field] = [0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +### push_front + +Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. + +```rust +fn push_front(_self: Self, _elem: T) -> Self +``` + +Example: + +```rust +let mut new_slice: [Field] = []; +new_slice = new_slice.push_front(20); +assert(new_slice[0] == 20); // returns true +``` + +View the corresponding test file [here][test-file]. + +### pop_front + +Returns a tuple of two items, the first element of the array and the rest of the array. + +```rust +fn pop_front(_self: Self) -> (T, Self) +``` + +Example: + +```rust +let (first_elem, rest_of_slice) = slice.pop_front(); +``` + +View the corresponding test file [here][test-file]. + +### pop_back + +Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. + +```rust +fn pop_back(_self: Self) -> (Self, T) +``` + +Example: + +```rust +let (popped_slice, last_elem) = slice.pop_back(); +``` + +View the corresponding test file [here][test-file]. + +### append + +Loops over a slice and adds it to the end of another. + +```rust +fn append(mut self, other: Self) -> Self +``` + +Example: + +```rust +let append = [1, 2].append([3, 4, 5]); +``` + +### insert + +Inserts an element at a specified index and shifts all following elements by 1. + +```rust +fn insert(_self: Self, _index: Field, _elem: T) -> Self +``` + +Example: + +```rust +new_slice = rest_of_slice.insert(2, 100); +assert(new_slice[2] == 100); +``` + +View the corresponding test file [here][test-file]. + +### remove + +Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. + +```rust +fn remove(_self: Self, _index: Field) -> (Self, T) +``` + +Example: + +```rust +let (remove_slice, removed_elem) = slice.remove(3); +``` diff --git a/docs/docs/explanations/noir/data_types/strings.md b/docs/docs/explanations/noir/data_types/strings.md new file mode 100644 index 0000000000..8d76d4ca65 --- /dev/null +++ b/docs/docs/explanations/noir/data_types/strings.md @@ -0,0 +1,80 @@ +--- +title: Strings +description: + Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. +keywords: + [ + noir, + string type, + methods, + examples, + concatenation, + ] +sidebar_position: 3 +--- + + +The string type is a fixed length value defined with `str`. + +You can use strings in `assert()` functions or print them with +`std::println()`. See more about [Logging](../../standard_library/logging). + +```rust +use dep::std; + +fn main(message : pub str<11>, hex_as_string : str<4>) { + std::println(message); + assert(message == "hello world"); + assert(hex_as_string == "0x41"); +} +``` + +You can convert a `str` to a byte array by calling `as_bytes()` +or a vector by calling `as_bytes_vec()`. + +```rust +fn main() { + let message = "hello world"; + let message_bytes = message.as_bytes(); + let mut message_vec = message.as_bytes_vec(); + assert(message_bytes.len() == 11); + assert(message_bytes[0] == 104); + assert(message_bytes[0] == message_vec.get(0)); +} +``` + +## Escape characters + +You can use escape characters for your strings: + +| Escape Sequence | Description | +|-----------------|-----------------| +| `\r` | Carriage Return | +| `\n` | Newline | +| `\t` | Tab | +| `\0` | Null Character | +| `\"` | Double Quote | +| `\\` | Backslash | + +Example: + +```rust +let s = "Hello \"world" // prints "Hello "world" +let s = "hey \tyou"; // prints "hey you" +``` + +## Raw strings + +A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. + +Escape characters are *not* processed within raw strings. All contents are interpreted literally. + +Example: + +```rust +let s = r"Hello world"; +let s = r#"Simon says "hello world""#; + +// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes +let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; +``` diff --git a/docs/docs/explanations/noir/data_types/structs.md b/docs/docs/explanations/noir/data_types/structs.md new file mode 100644 index 0000000000..dbf68c9981 --- /dev/null +++ b/docs/docs/explanations/noir/data_types/structs.md @@ -0,0 +1,70 @@ +--- +title: Structs +description: + Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. +keywords: + [ + noir, + struct type, + methods, + examples, + data structures, + ] +sidebar_position: 8 +--- + +A struct also allows for grouping multiple values of different types. Unlike tuples, we can also +name each field. + +> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the +> field type of Noir. + +Defining a struct requires giving it a name and listing each field within as `: ` pairs: + +```rust +struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +An instance of a struct can then be created with actual values in `: ` pairs in any +order. Struct fields are accessible using their given names: + +```rust +fn main() { + let legs = 4; + + let dog = Animal { + eyes: 2, + hands: 0, + legs, + }; + + let zero = dog.hands; +} +``` + +Structs can also be destructured in a pattern, binding each field to a new variable: + +```rust +fn main() { + let Animal { hands, legs: feet, eyes } = get_octopus(); + + let ten = hands + feet + eyes as u8; +} + +fn get_octopus() -> Animal { + let octopus = Animal { + hands: 0, + legs: 8, + eyes: 2, + }; + + octopus +} +``` + +The new variables can be bound with names different from the original struct field names, as +showcased in the `legs --> feet` binding in the example above. diff --git a/docs/docs/explanations/noir/data_types/tuples.md b/docs/docs/explanations/noir/data_types/tuples.md new file mode 100644 index 0000000000..2ec5c9c411 --- /dev/null +++ b/docs/docs/explanations/noir/data_types/tuples.md @@ -0,0 +1,48 @@ +--- +title: Tuples +description: + Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. +keywords: + [ + noir, + tuple type, + methods, + examples, + multi-value containers, + ] +sidebar_position: 7 +--- + +A tuple collects multiple values like an array, but with the added ability to collect values of +different types: + +```rust +fn main() { + let tup: (u8, u64, Field) = (255, 500, 1000); +} +``` + +One way to access tuple elements is via destructuring using pattern matching: + +```rust +fn main() { + let tup = (1, 2); + + let (one, two) = tup; + + let three = one + two; +} +``` + +Another way to access tuple elements is via direct member access, using a period (`.`) followed by +the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to +the second and so on: + +```rust +fn main() { + let tup = (5, 6, 7, 8); + + let five = tup.0; + let eight = tup.3; +} +``` diff --git a/docs/docs/explanations/noir/data_types/vectors.mdx b/docs/docs/explanations/noir/data_types/vectors.mdx new file mode 100644 index 0000000000..10e35711b7 --- /dev/null +++ b/docs/docs/explanations/noir/data_types/vectors.mdx @@ -0,0 +1,173 @@ +--- +title: Vectors +description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. +keywords: [noir, vector type, methods, examples, dynamic arrays] +sidebar_position: 6 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. + +Example: + +```rust +use dep::std::collections::vec::Vec; + +let mut vector: Vec = Vec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +``` + +## Methods + +### new + +Creates a new, empty vector. + +```rust +pub fn new() -> Self { + Self { slice: [] } +} +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### from_slice + +Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. + +```rust +pub fn from_slice(slice: [T]) -> Self { + Self { slice } +} +``` + +Example: + +```rust +let arr: [Field] = [1, 2, 3]; +let vector_from_slice = Vec::from_slice(arr); +assert(vector_from_slice.len() == 3); +``` + +### get + +Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. + +```rust +pub fn get(self, index: Field) -> T { + self.slice[index] +} +``` + +Example: + +```rust +let vector: Vec = Vec::from_slice([10, 20, 30]); +assert(vector.get(1) == 20); +``` + +### push + +Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. + +```rust +pub fn push(&mut self, elem: T) { + self.slice = self.slice.push_back(elem); +} +``` + +Example: + +```rust +let mut vector: Vec = Vec::new(); +vector.push(10); +assert(vector.len() == 1); +``` + +### pop + +Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. + +```rust +pub fn pop(&mut self) -> T { + let (popped_slice, last_elem) = self.slice.pop_back(); + self.slice = popped_slice; + last_elem +} +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 20]); +let popped_elem = vector.pop(); +assert(popped_elem == 20); +assert(vector.len() == 1); +``` + +### insert + +Inserts an element at a specified index, shifting subsequent elements to the right. + +```rust +pub fn insert(&mut self, index: Field, elem: T) { + self.slice = self.slice.insert(index, elem); +} +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 30]); +vector.insert(1, 20); +assert(vector.get(1) == 20); +``` + +### remove + +Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. + +```rust +pub fn remove(&mut self, index: Field) -> T { + let (new_slice, elem) = self.slice.remove(index); + self.slice = new_slice; + elem +} +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 20, 30]); +let removed_elem = vector.remove(1); +assert(removed_elem == 20); +assert(vector.len() == 2); +``` + +### len + +Returns the number of elements in the vector. + +```rust +pub fn len(self) -> Field { + self.slice.len() +} +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` diff --git a/docs/docs/explanations/noir/distinct.md b/docs/docs/explanations/noir/distinct.md new file mode 100644 index 0000000000..b59e0296b2 --- /dev/null +++ b/docs/docs/explanations/noir/distinct.md @@ -0,0 +1,64 @@ +--- +title: Distinct Witnesses +sidebar_position: 10 +--- + +The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures +that the witnesses being returned as public inputs are all unique. + +The `distinct` keyword is only used for return values on program entry points (usually the `main()` +function). + +When using `distinct` and `pub` simultaneously, `distinct` comes first. See the example below. + +You can read more about the problem this solves +[here](https://github.com/noir-lang/noir/issues/1183). + +## Example + +Without the `distinct` keyword, the following program + +```rust +fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { + let a = 1; + let b = 1; + [x + 1, y, a, b] +} +``` + +compiles to + +```json +{ + //... + "abi": { + //... + "param_witnesses": { "x": [1], "y": [2] }, + "return_witnesses": [3, 2, 4, 4] + } +} +``` + +Whereas (with the `distinct` keyword) + +```rust +fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { + let a = 1; + let b = 1; + [x + 1, y, a, b] +} +``` + +compiles to + +```json +{ + //... + "abi": { + //... + "param_witnesses": { "x": [1], "y": [2] }, + //... + "return_witnesses": [3, 4, 5, 6] + } +} +``` diff --git a/docs/docs/explanations/noir/functions.md b/docs/docs/explanations/noir/functions.md new file mode 100644 index 0000000000..94f929038e --- /dev/null +++ b/docs/docs/explanations/noir/functions.md @@ -0,0 +1,226 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +sidebar_position: 1 +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](@site/docs/explanations/modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](@site/docs/getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main([1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](@site/docs/reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](@site/docs/getting_started/tooling/testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/docs/docs/explanations/noir/generics.md b/docs/docs/explanations/noir/generics.md new file mode 100644 index 0000000000..443ca2b45a --- /dev/null +++ b/docs/docs/explanations/noir/generics.md @@ -0,0 +1,114 @@ +--- +title: Generics +description: Learn how to use Generics in Noir +keywords: [Noir, Rust, generics, functions, structs] +sidebar_position: 6 +--- + +Generics allow you to use the same functions with multiple different concrete data types. You can +read more about the concept of generics in the Rust documentation +[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). + +Here is a trivial example showing the identity function that supports any type. In Rust, it is +common to refer to the most general type as `T`. We follow the same convention in Noir. + +```rust +fn id(x: T) -> T { + x +} +``` + +## In Structs + +Generics are useful for specifying types in structs. For example, we can specify that a field in a +struct will be of a certain generic type. In this case `value` is of type `T`. + +```rust +struct RepeatedValue { + value: T, + count: Field, +} + +impl RepeatedValue { + fn new(value: T) -> Self { + Self { value, count: 1 } + } + + fn increment(mut repeated: Self) -> Self { + repeated.count += 1; + repeated + } + + fn print(self) { + for _i in 0 .. self.count { + dep::std::println(self.value); + } + } +} + +fn main() { + let mut repeated = RepeatedValue::new("Hello!"); + repeated = repeated.increment(); + repeated.print(); +} +``` + +The `print` function will print `Hello!` an arbitrary number of times, twice in this case. + +If we want to be generic over array lengths (which are type-level integers), we can use numeric +generics. Using these looks just like using regular generics, but these generics can resolve to +integers at compile-time, rather than resolving to types. Here's an example of a struct that is +generic over the size of the array it contains internally: + +```rust +struct BigInt { + limbs: [u32; N], +} + +impl BigInt { + // `N` is in scope of all methods in the impl + fn first(first: BigInt, second: BigInt) -> Self { + assert(first.limbs != second.limbs); + first + + fn second(first: BigInt, second: Self) -> Self { + assert(first.limbs != second.limbs); + second + } +} +``` + +## Calling functions on generic parameters + +Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in +Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also +requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? + +The answer is that we can translate this by passing in the function manually. Here's an example of +implementing array equality in Noir: + +```rust +fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { + if array1.len() != array2.len() { + false + } else { + let mut result = true; + for i in 0 .. array1.len() { + result &= elem_eq(array1[i], array2[i]); + } + result + } +} + +fn main() { + assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); + + // We can use array_eq even for arrays of structs, as long as we have + // an equality function for these structs we can pass in + let array = [MyStruct::new(), MyStruct::new()]; + assert(array_eq(array, array, MyStruct::eq)); +} +``` + +You can see an example of generics in the tests +[here](https://github.com/noir-lang/noir/blob/master/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). diff --git a/docs/docs/explanations/noir/lambdas.md b/docs/docs/explanations/noir/lambdas.md new file mode 100644 index 0000000000..e0a267adfd --- /dev/null +++ b/docs/docs/explanations/noir/lambdas.md @@ -0,0 +1,81 @@ +--- +title: Lambdas +description: Learn how to use anonymous functions in Noir programming language. +keywords: [Noir programming language, lambda, closure, function, anonymous function] +sidebar_position: 8 +--- + +## Introduction + +Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +A block can be used as the body of a lambda, allowing you to declare local variables inside it: + +```rust +let cool = || { + let x = 100; + let y = 100; + x + y +} + +assert(cool() == 200); +``` + +## Closures + +Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: + +```rust +fn main() { + let x = 100; + let closure = || x + 150; + assert(closure() == 250); +} +``` + +## Passing closures to higher-order functions + +It may catch you by surprise that the following code fails to compile: + +```rust +fn foo(f: fn () -> Field) -> Field { + f() +} + +fn main() { + let (x, y) = (50, 50); + assert(foo(|| x + y) == 100); // error :( +} +``` + +The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` +expects a regular function as an argument - those are incompatible. +:::note + +Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. + +E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. + +::: +The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - +in this example that's `(Field, Field)`. + +The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called +with closures with any environment, as well as with regular functions: + +```rust +fn foo(f: fn[Env]() -> Field) -> Field { + f() +} + +fn main() { + let (x, y) = (50, 50); + assert(foo(|| x + y) == 100); // compiles fine + assert(foo(|| 60) == 60); // compiles fine +} +``` diff --git a/docs/docs/explanations/noir/mutability.md b/docs/docs/explanations/noir/mutability.md new file mode 100644 index 0000000000..58e9c1cecf --- /dev/null +++ b/docs/docs/explanations/noir/mutability.md @@ -0,0 +1,93 @@ +--- +title: Mutability +description: + Learn about mutable variables, constants, and globals in Noir programming language. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] +sidebar_position: 7 +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Comptime Values + +:::warning + +The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. + +::: + +## Globals + +Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array +annotations for function parameters and can be imported from submodules. + +```rust +global N: Field = 5; // Same as `global N: Field = 5` + +fn main(x : Field, y : [Field; N]) { + let res = x * N; + + assert(res == y[0]); + + let res2 = x * mysubmodule::N; + assert(res != res2); +} + +mod mysubmodule { + use dep::std; + + global N: Field = 10; + + fn my_helper() -> Field { + let x = N; + x + } +} +``` + +## Why only local mutability? + +Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting +without applying additional overhead to the user. Modeling a mutable reference is not as +straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/docs/explanations/noir/ops.md b/docs/docs/explanations/noir/ops.md new file mode 100644 index 0000000000..977c8ba120 --- /dev/null +++ b/docs/docs/explanations/noir/ops.md @@ -0,0 +1,98 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +sidebar_position: 3 +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | +| >> | Right shift an integer by another integer amount | Types must be integer | +| ! | Bitwise not of a value | Type must be integer or boolean | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | +| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | +| == | returns a bool if one value is equal to the other | Both types must not be constants | +| != | returns a bool if one value is not equal to the other | Both types must not be constants | + +### Predicate Operators + +`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. +This differs from the operations such as `+` where the operands are used in _computation_. + +### Bitwise Operations Example + +```rust +fn main(x : Field) { + let y = x as u32; + let z = y & y; +} +``` + +`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise +`&`. + +> `x & x` would not compile as `x` is a `Field` and not an integer type. + +### Logical Operators + +Noir has no support for the logical operators `||` and `&&`. This is because encoding the +short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can +use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +short-circuiting. + +```rust +let my_val = 5; + +let mut flag = 1; +if (my_val > 6) | (my_val == 0) { + flag = 0; +} +assert(flag == 1); + +if (my_val != 10) & (my_val < 50) { + flag = 0; +} +assert(flag == 0); +``` + +### Shorthand operators + +Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: + +```rust +let mut i = 0; +i = i + 1; +``` + +could be written as: + +```rust +let mut i = 0; +i += 1; +``` diff --git a/docs/docs/explanations/noir/shadowing.md b/docs/docs/explanations/noir/shadowing.md new file mode 100644 index 0000000000..b5a6b6b38b --- /dev/null +++ b/docs/docs/explanations/noir/shadowing.md @@ -0,0 +1,44 @@ +--- +title: Shadowing +sidebar_position: 11 +--- + +Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. + +For example, the following function is valid in Noir: + +```rust +fn main() { + let x = 5; + + { + let x = x * 2; + assert (x == 10); + } + + assert (x == 5); +} +``` + +In this example, a variable x is first defined with the value 5. + +The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. + +When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. + +## Temporal mutability + +One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. + +```rust +fn main() { + let age = 30; + // age = age + 5; // Would error as `age` is immutable by default. + + let mut age = age + 5; // Temporarily mutates `age` with a new value. + + let age = age; // Locks `age`'s mutability again. + + assert (age == 35); +} +``` diff --git a/docs/docs/explanations/noir/traits.md b/docs/docs/explanations/noir/traits.md new file mode 100644 index 0000000000..d24deaa84d --- /dev/null +++ b/docs/docs/explanations/noir/traits.md @@ -0,0 +1,348 @@ +--- +title: Traits +description: + Traits in Noir can be used to abstract out a common interface for functions across + several data types. +keywords: [noir programming language, traits, interfaces, generic, protocol] +--- + +## Overview + +Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines +the interface of several methods contained within the trait. Types can then implement this trait by providing +implementations for these methods. For example in the program: + +```rust +struct Rectangle { + width: Field, + height: Field, +} + +impl Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +fn log_area(r: Rectangle) { + println(r.area()); +} +``` + +We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this +function to work on `Triangle`s as well?: + +```rust +struct Triangle { + width: Field, + height: Field, +} + +impl Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can +introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: + +```rust +trait Area { + fn area(self) -> Field; +} + +fn log_area(shape: S) where S: Area { + println(shape.area()); +} +``` + +We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing +impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined +by the `Area` trait. + +```rust +impl Area for Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +impl Area for Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Now we have a working program that is generic over any type of Shape that is used! Others can even use this program +as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. + +## Where Clauses + +As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements +a trait, we can add a where clause to the generic function. + +```rust +fn log_area(shape: S) where S: Area { + println(shape.area()); +} +``` + +It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` +operator. Similarly, we can have multiple trait constraints by separating each with a comma: + +```rust +fn foo(elements: [T], thing: U) where + T: Default + Add + Eq, + U: Bar, +{ + let mut sum = T::default(); + + for element in elements { + sum += element; + } + + if sum == T::default() { + thing.bar(); + } +} +``` + +## Generic Implementations + +You can add generics to a trait implementation by adding the generic list after the `impl` keyword: + +```rust +trait Second { + fn second(self) -> Field; +} + +impl Second for (T, Field) { + fn second(self) -> Field { + self.1 + } +} +``` + +You can also implement a trait for every type this way: + +```rust +trait Debug { + fn debug(self); +} + +impl Debug for T { + fn debug(self) { + println(self); + } +} + +fn main() { + 1.debug(); +} +``` + +### Generic Trait Implementations With Where Clauses + +Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` +will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. +For example, here is the implementation for array equality: + +```rust +impl Eq for [T; N] where T: Eq { + // Test if two arrays have the same elements. + // Because both arrays must have length N, we know their lengths already match. + fn eq(self, other: Self) -> bool { + let mut result = true; + + for i in 0 .. self.len() { + // The T: Eq constraint is needed to call == on the array elements here + result &= self[i] == other[i]; + } + + result + } +} +``` + +## Trait Methods With No `self` + +A trait can contain any number of methods, each of which have access to the `Self` type which represents each type +that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. +For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type +but doesn't need to take any parameters: + +```rust +trait Default { + fn default() -> Self; +} +``` + +Implementing this trait can be done similarly to any other trait: + +```rust +impl Default for Field { + fn default() -> Field { + 0 + } +} + +struct MyType {} + +impl Default for MyType { + fn default() -> Field { + MyType {} + } +} +``` + +However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. +Instead, we'll need to refer to the function directly. This can be done either by referring to the +specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later +case, type inference determines the impl that is selected. + +```rust +let my_struct = MyStruct::default(); + +let x: Field = Default::default(); +let result = x + Default::default(); +``` + +:::warning + +```rust +let _ = Default::default(); +``` + +If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be +arbitrarily selected. This occurs most often when the result of a trait function call with no parameters +is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, +always refer to it via the implementation type's namespace - e.g. `MyType::default()`. +This is set to change to an error in future Noir versions. + +::: + +## Default Method Implementations + +A trait can also have default implementations of its methods by giving a body to the desired functions. +Note that this body must be valid for all types that may implement the trait. As a result, the only +valid operations on `self` will be operations valid for any type or other operations on the trait itself. + +```rust +trait Numeric { + fn add(self, other: Self) -> Self; + + // Default implementation of double is (self + self) + fn double(self) -> Self { + self.add(self) + } +} +``` + +When implementing a trait with default functions, a type may choose to implement only the required functions: + +```rust +impl Numeric for Field { + fn add(self, other: Field) -> Field { + self + other + } +} +``` + +Or it may implement the optional methods as well: + +```rust +impl Numeric for u32 { + fn add(self, other: u32) -> u32 { + self + other + } + + fn double(self) -> u32 { + self * 2 + } +} +``` + +## Impl Specialization + +When implementing traits for a generic type it is possible to implement the trait for only a certain combination +of generics. This can be either as an optimization or because those specific generics are required to implement the trait. + +```rust +trait Sub { + fn sub(self, other: Self) -> Self; +} + +struct NonZero { + value: T, +} + +impl Sub for NonZero { + fn sub(self, other: Self) -> Self { + let value = self.value - other.value; + assert(value != 0); + NonZero { value } + } +} +``` + +## Overlapping Implementations + +Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. +This means if a trait `Foo` is already implemented +by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other +type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create +any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given +method call. + +```rust +trait Trait {} + +// Previous impl defined here +impl Trait for (A, B) {} + +// error: Impl for type `(Field, Field)` overlaps with existing impl +impl Trait for (Field, Field) {} +``` + +## Trait Coherence + +Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create +impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same +program. + +The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared +in the crate the impl is in. + +In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does +not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. +While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its +own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the +library your choices are to either submit a patch to the library or use the newtype pattern. + +### The Newtype Pattern + +The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type +that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create +impls for any trait we need on it. + +```rust +struct Wrapper { + foo: dep::some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: dep::some_library::Foo::new(), + } + } +} +``` + +Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated +to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and +unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/docs/docs/explanations/noir/unconstrained.md b/docs/docs/explanations/noir/unconstrained.md new file mode 100644 index 0000000000..7a61d3953e --- /dev/null +++ b/docs/docs/explanations/noir/unconstrained.md @@ -0,0 +1,95 @@ +--- +title: Unconstrained Functions +description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." + +keywords: [Noir programming language, unconstrained, open] +sidebar_position: 5 +--- + +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-determinisitic computation. + +## Why? + +Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. + +Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. + +Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. + +A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. + +## Example + +An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. + +Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. + +```rust +fn main(num: u72) -> pub [u8; 8] { + let mut out: [u8; 8] = [0; 8]; + for i in 0..8 { + out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; + } + + out +} +``` + +``` +Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 +Backend circuit size: 3619 +``` + +A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the XOR against 0xff. This saves us ~480 gates in total. + +```rust +fn main(num: u72) -> pub [u8; 8] { + let mut out: [u8; 8] = [0; 8]; + for i in 0..8 { + out[i] = (num >> (56 - (i * 8)) as u8; + } + + out +} +``` + +``` +Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 +Backend circuit size: 3143 +``` + +Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. + +It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. + +We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: + +```rust +fn main(num: u72) -> pub [u8; 8] { + let out = u72_to_u8(num); + + let mut reconstructed_num: u72 = 0; + for i in 0..8 { + reconstructed_num += (out[i] as u72 << (56 - (8 * i))); + } + assert(num == reconstructed_num); + out +} + +unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { + let mut out: [u8; 8] = [0; 8]; + for i in 0..8 { + out[i] = (num >> (56 - (i * 8))) as u8; + } + out +} +``` + +``` +Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 +Backend circuit size: 2902 +``` + +This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). + +Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. diff --git a/docs/docs/explanations/standard_library/_category_.json b/docs/docs/explanations/standard_library/_category_.json new file mode 100644 index 0000000000..af04c0933f --- /dev/null +++ b/docs/docs/explanations/standard_library/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Standard Library", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/standard_library/black_box_fns.md b/docs/docs/explanations/standard_library/black_box_fns.md similarity index 100% rename from docs/docs/standard_library/black_box_fns.md rename to docs/docs/explanations/standard_library/black_box_fns.md diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/_category_.json b/docs/docs/explanations/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 0000000000..5d694210bb --- /dev/null +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/ec_primitives.md b/docs/docs/explanations/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 0000000000..8d573adb3b --- /dev/null +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/ec_primitives.md @@ -0,0 +1,102 @@ +--- +title: Elliptic Curve Primitives +keywords: [cryptographic primitives, Noir project] +sidebar_position: 4 +--- + +Data structures and methods on them that allow you to carry out computations involving elliptic +curves over the (mathematical) field corresponding to `Field`. For the field currently at our +disposal, applications would involve a curve embedded in BN254, e.g. the +[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). + +## Data structures + +### Elliptic curve configurations + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic +curve you want to use, which would be specified using any one of the methods +`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the +defining equation together with a generator point as parameters. You can find more detail in the +comments in +[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +the gist of it is that the elliptic curves of interest are usually expressed in one of the standard +forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, +you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly +together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates +requiring more coordinates but allowing for more efficient implementations of elliptic curve +operations). Conversions between all of these forms are provided, and under the hood these +conversions are done whenever an operation is more efficient in a different representation (or a +mixed coordinate representation is employed). + +### Points + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the +elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` +does indeed lie on `c` by calling `c.contains(p1)`. + +## Methods + +(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use +`std::ec::tecurve::affine::Point`) + +- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is + zero by calling `p.is_zero()`. +- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling + `p1.eq(p2)`. +- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two + points is accomplished by calling `c.add(p1,p2)`. +- **Negation**: For a point `p: Point`, `p.negate()` is its negation. +- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by + calling `c.subtract(p1,p2)`. +- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, + scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit + array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` +- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, + multi-scalar multiplication is given by `c.msm(n,p)`. +- **Coordinate representation conversions**: The `into_group` method converts a point or curve + configuration in the affine representation to one in the CurveGroup representation, and + `into_affine` goes in the other direction. +- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent + and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their + configurations or points. `swcurve` is more general and a curve c of one of the other two types + may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying + on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling + `c.map_into_swcurve(p)`. +- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a + `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of + the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where + `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to + satisfy are specified in the comments + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + +## Examples + +The +[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/crates/nargo_cli/tests/test_data/ec_baby_jubjub/src/main.nr) +illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more +interesting examples in Noir would be: + +Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key +from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, +for example, this code would do: + +```rust +use dep::std::ec::tecurve::affine::{Curve, Point}; + +fn bjj_pub_key(priv_key: Field) -> Point +{ + + let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); + + let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); + + bjj.mul(priv_key,base_pt) +} +``` + +This would come in handy in a Merkle proof. + +- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash + function. See + [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for + the case of Baby Jubjub and the Poseidon hash function. diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/docs/docs/explanations/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 0000000000..1376c51dfd --- /dev/null +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -0,0 +1,46 @@ +--- +title: ECDSA Signature Verification +description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves +keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +sidebar_position: 3 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. + +## ecdsa_secp256k1::verify_signature + +Verifier for ECDSA Secp256k1 signatures + +```rust +fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool +``` + +example: + +```rust +fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { + let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} +``` + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures + +```rust +fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool +``` + +example: + +```rust +fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { + let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} +``` + + diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/eddsa.mdx b/docs/docs/explanations/standard_library/cryptographic_primitives/eddsa.mdx new file mode 100644 index 0000000000..a9c10da6c0 --- /dev/null +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/eddsa.mdx @@ -0,0 +1,18 @@ +--- +title: EdDSA Verification +description: Learn about the cryptographic primitives regarding EdDSA +keywords: [cryptographic primitives, Noir project, eddsa, signatures] +sidebar_position: 5 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## eddsa::eddsa_poseidon_verify + +Verifier for EdDSA signatures + +```rust +fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool +``` + + diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/hashes.mdx b/docs/docs/explanations/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 0000000000..9250cb4a0c --- /dev/null +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,168 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s, pedersen, mimc_bn254 and mimc +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## sha256 + +Given an array of bytes, returns the resulting sha256 hash. + +```rust +fn sha256(_input : [u8]) -> [u8; 32] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::sha256(x); +} +``` + + + +## blake2s + +Given an array of bytes, returns an array with the Blake2 hash + +```rust +fn blake2s(_input : [u8]) -> [u8; 32] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake2s(x); +} +``` + + + +## pedersen_hash + +Given an array of Fields, returns the Pedersen hash. + +```rust +fn pedersen_hash(_input : [Field]) -> Field +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::pedersen_hash(x); +} +``` + + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust +fn pedersen_commitment(_input : [Field]) -> [Field; 2] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let commitment = std::hash::pedersen_commitment(x); +} +``` + + + +## keccak256 + +Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes +(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes +of the input. + +```rust +fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let message_size = 4; + let hash = std::hash::keccak256(x, message_size); +} +``` + + + +## poseidon + +Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify +how many inputs are there to your Poseidon function. + +```rust +// example for hash_1, hash_2 accepts an array of length 2, etc +fn hash_1(input: [Field; 1]) -> Field +``` + +example: + +```rust +fn main() +{ + let hash_2 = std::hash::poseidon::bn254::hash_2([1, 2]); + assert(hash2 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); +} +``` + +## mimc_bn254 and mimc + +`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by +providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if +you're willing to input your own constants: + +```rust +fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field +``` + +otherwise, use the `mimc_bn254` method: + +```rust +fn mimc_bn254(array: [Field; N]) -> Field +``` + +example: + +```rust + +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::mimc::mimc_bn254(x); +} +``` + +## hash_to_field + +```rust +fn hash_to_field(_input : [Field; N]) -> Field {} +``` + +Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return +a value which can be represented as a `Field`. + + diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/index.md b/docs/docs/explanations/standard_library/cryptographic_primitives/index.md new file mode 100644 index 0000000000..650f30165d --- /dev/null +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/index.md @@ -0,0 +1,14 @@ +--- +title: Cryptographic Primitives +description: + Learn about the cryptographic primitives ready to use for any Noir project +keywords: + [ + cryptographic primitives, + Noir project, + ] +--- + +The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. + +Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/scalar.mdx b/docs/docs/explanations/standard_library/cryptographic_primitives/scalar.mdx new file mode 100644 index 0000000000..1e686303c1 --- /dev/null +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/scalar.mdx @@ -0,0 +1,28 @@ +--- +title: Scalar multiplication +description: See how you can perform scalar multiplications over a fixed base in Noir +keywords: [cryptographic primitives, Noir project, scalar multiplication] +sidebar_position: 1 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## scalar_mul::fixed_base_embedded_curve + +Performs scalar multiplication over the embedded curve whose coordinates are defined by the +configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. + +```rust +fn fixed_base_embedded_curve(_input : Field) -> [Field; 2] +``` + +example + +```rust +fn main(x : Field) { + let scal = std::scalar_mul::fixed_base_embedded_curve(x); + std::println(scal); +} +``` + + diff --git a/docs/docs/explanations/standard_library/cryptographic_primitives/schnorr.mdx b/docs/docs/explanations/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 0000000000..7a2c9c2022 --- /dev/null +++ b/docs/docs/explanations/standard_library/cryptographic_primitives/schnorr.mdx @@ -0,0 +1,38 @@ +--- +title: Schnorr Signatures +description: Learn how you can verify Schnorr signatures using Noir +keywords: [cryptographic primitives, Noir project, schnorr, signatures] +sidebar_position: 2 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## schnorr::verify_signature + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). + +```rust +fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool +``` + +where `_signature` can be generated like so using the npm package +[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) + +```js +const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); +const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); + +... + +const barretenberg = await BarretenbergWasm.new(); +const schnorr = new Schnorr(barretenberg); +const pubKey = schnorr.computePublicKey(privateKey); +const message = ... +const signature = Array.from( + schnorr.constructSignature(hash, privateKey).toBuffer() +); + +... +``` + + diff --git a/docs/docs/explanations/standard_library/logging.md b/docs/docs/explanations/standard_library/logging.md new file mode 100644 index 0000000000..16daf922e1 --- /dev/null +++ b/docs/docs/explanations/standard_library/logging.md @@ -0,0 +1,77 @@ +--- +title: Logging +description: + Learn how to use the println statement for debugging in Noir with this tutorial. Understand the + basics of logging in Noir and how to implement it in your code. +keywords: + [ + noir logging, + println statement, + print statement, + debugging in noir, + noir std library, + logging tutorial, + basic logging in noir, + noir logging implementation, + noir debugging techniques, + rust, + ] +--- + +The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. + +You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). + +It is recommended to use `nargo execute` if you want to debug failing constrains with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. + +Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: + +```rust +use dep::std; + +struct Person { + age : Field, + height : Field, +} + +fn main(age : Field, height : Field) { + let person = Person { age : age, height : height }; + std::println(person); + std::println(age + height); + std::println("Hello world!"); +} +``` + +You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: + +```rust + let fmt_str = f"i: {i}, j: {j}"; + std::println(fmt_str); + + let s = myStruct { y: x, x: y }; + std::println(s); + + std::println(f"i: {i}, s: {s}"); + + std::println(x); + std::println([x, y]); + + let foo = fooStruct { my_struct: s, foo: 15 }; + std::println(f"s: {s}, foo: {foo}"); + + std::println(15); // prints 0x0f, implicit Field + std::println(-1 as u8); // prints 255 + std::println(-1 as i8); // prints -1 +``` + +Examples shown above are interchangeable between the two `print` statements: + +```rust +let person = Person { age : age, height : height }; + +std::println(person); +std::print(person); + +std::println("Hello world!"); // Prints with a newline at the end of the input +std::print("Hello world!"); // Prints the input and keeps cursor on the same line +``` diff --git a/docs/docs/explanations/standard_library/merkle_trees.md b/docs/docs/explanations/standard_library/merkle_trees.md new file mode 100644 index 0000000000..07fa2ccda7 --- /dev/null +++ b/docs/docs/explanations/standard_library/merkle_trees.md @@ -0,0 +1,58 @@ +--- +title: Merkle Trees +description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. +keywords: + [ + Merkle trees in Noir, + Noir programming language, + check membership, + computing root from leaf, + Noir Merkle tree implementation, + Merkle tree tutorial, + Merkle tree code examples, + Noir libraries, + pedersen hash., + ] +--- + +## compute_merkle_root + +Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](@site/docs/explanations/standard_library/cryptographic_primitives/hashes.mdx#pedersen_hash). + +```rust +fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field +``` + +example: + +```rust +/** + // these values are for this example only + index = "0" + priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" + secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" + note_hash_path = [ + "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", + "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", + "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" + ] + */ +fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { + + let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); + let pubkey_x = pubkey[0]; + let pubkey_y = pubkey[1]; + let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); + + let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); + std::println(root); +} +``` + +To check merkle tree membership: + +1. Include a merkle root as a program input. +2. Compute the merkle root of a given leaf, index and hash path. +3. Assert the merkle roots are equal. + +For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/docs/docs/standard_library/options.md b/docs/docs/explanations/standard_library/options.md similarity index 100% rename from docs/docs/standard_library/options.md rename to docs/docs/explanations/standard_library/options.md diff --git a/docs/docs/standard_library/recursion.md b/docs/docs/explanations/standard_library/recursion.md similarity index 100% rename from docs/docs/standard_library/recursion.md rename to docs/docs/explanations/standard_library/recursion.md diff --git a/docs/docs/explanations/standard_library/traits.md b/docs/docs/explanations/standard_library/traits.md new file mode 100644 index 0000000000..63b4f3d6f0 --- /dev/null +++ b/docs/docs/explanations/standard_library/traits.md @@ -0,0 +1,140 @@ +--- +title: Traits +description: Noir's stdlib provides a few commonly used traits. +keywords: [traits, trait, interface, protocol, default, add, eq] +--- + +## `std::default` + +### `std::default::Default` + +```rust +trait Default { + fn default() -> Self; +} +``` + +Constructs a default value of a type. + +Implementations: +```rust +impl Default for Field { .. } + +impl Default for i8 { .. } +impl Default for i16 { .. } +impl Default for i32 { .. } +impl Default for i64 { .. } + +impl Default for u8 { .. } +impl Default for u16 { .. } +impl Default for u32 { .. } +impl Default for u64 { .. } + +impl Default for () { .. } +impl Default for bool { .. } + +impl Default for [T; N] + where T: Default { .. } + +impl Default for (A, B) + where A: Default, B: Default { .. } + +impl Default for (A, B, C) + where A: Default, B: Default, C: Default { .. } + +impl Default for (A, B, C, D) + where A: Default, B: Default, C: Default, D: Default { .. } + +impl Default for (A, B, C, D, E) + where A: Default, B: Default, C: Default, D: Default, E: Default { .. } +``` + +For primitive integer types, the return value of `default` is `0`. Container +types such as arrays are filled with default values of their element type. + +## `std::ops` + +### `std::ops::Eq` + +```rust +trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +Returns `true` if `self` is equal to `other`. + +Implementations: +```rust +impl Eq for Field { .. } + +impl Eq for i8 { .. } +impl Eq for i16 { .. } +impl Eq for i32 { .. } +impl Eq for i64 { .. } + +impl Eq for u8 { .. } +impl Eq for u16 { .. } +impl Eq for u32 { .. } +impl Eq for u64 { .. } + +impl Eq for () { .. } +impl Eq for bool { .. } + +impl Eq for [T; N] + where T: Eq { .. } + +impl Eq for (A, B) + where A: Eq, B: Eq { .. } + +impl Eq for (A, B, C) + where A: Eq, B: Eq, C: Eq { .. } + +impl Eq for (A, B, C, D) + where A: Eq, B: Eq, C: Eq, D: Eq { .. } + +impl Eq for (A, B, C, D, E) + where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } +``` + +### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` + +These traits abstract over addition, subtraction, multiplication, and division respectively. +Although Noir does not currently have operator overloading, in the future implementing these +traits for a given type will also allow that type to be used with the corresponding operator +for that trait (`+` for Add, etc) in addition to the normal method names. + +```rust +trait Add { + fn add(self, other: Self) -> Self; +} + +trait Sub { + fn sub(self, other: Self) -> Self; +} + +trait Mul { + fn mul(self, other: Self) -> Self; +} + +trait Div { + fn div(self, other: Self) -> Self; +} +``` + +The implementations block below is given for the `Add` trait, but the same types that implement +`Add` also implement `Sub`, `Mul`, and `Div`. + +Implementations: +```rust +impl Add for Field { .. } + +impl Add for i8 { .. } +impl Add for i16 { .. } +impl Add for i32 { .. } +impl Add for i64 { .. } + +impl Add for u8 { .. } +impl Add for u16 { .. } +impl Add for u32 { .. } +impl Add for u64 { .. } +``` diff --git a/docs/docs/standard_library/zeroed.md b/docs/docs/explanations/standard_library/zeroed.md similarity index 100% rename from docs/docs/standard_library/zeroed.md rename to docs/docs/explanations/standard_library/zeroed.md diff --git a/docs/docs/getting_started/00_nargo_installation.md b/docs/docs/getting_started/00_nargo_installation.md deleted file mode 100644 index 725c5f4d37..0000000000 --- a/docs/docs/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noir_js.md). - -### UltraPlonk - -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Compile from Source](#option-3-compile-from-source) -- [Option 4: WSL for Windows](#option-4-wsl-for-windows) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). - -Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -### Option 4: WSL (for Windows) - -The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). - -Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. - -step 2: Follow the [Noirup instructions](#option-1-noirup). - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/docs/docs/getting_started/_category_.json b/docs/docs/getting_started/_category_.json new file mode 100644 index 0000000000..5d694210bb --- /dev/null +++ b/docs/docs/getting_started/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/getting_started/create_a_project.md b/docs/docs/getting_started/create_a_project.md new file mode 100644 index 0000000000..76bed5be9b --- /dev/null +++ b/docs/docs/getting_started/create_a_project.md @@ -0,0 +1,142 @@ +--- +title: Creating A Project +description: + Learn how to create and verify your first Noir program using Nargo, a programming language for + zero-knowledge proofs. +keywords: + [ + Nargo, + Noir, + zero-knowledge proofs, + programming language, + create Noir program, + verify Noir program, + step-by-step guide, + ] +sidebar_position: 1 + +--- + +Now that we have installed Nargo, it is time to make our first hello world program! + +## Create a Project Directory + +Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home +directory to house our Noir programs. + +For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by +running: + +```sh +mkdir ~/projects +cd ~/projects +``` + +## Create Our First Nargo Project + +Now that we are in the projects directory, create a new Nargo project by running: + +```sh +nargo new hello_world +``` + +> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for +> demonstration. +> +> In production, the common practice is to name the project folder as `circuits` for better +> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, +> `test`). + +A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and +_Nargo.toml_ that contains the source code and environmental options of your Noir program +respectively. + +### Intro to Noir Syntax + +Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +The first line of the program specifies the program's inputs: + +```rust +x : Field, y : pub Field +``` + +Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the +keyword `pub` (e.g. `y`). To learn more about private and public values, check the +[Data Types](@site/docs/explanations/noir/data_types/index.md) section. + +The next line of the program specifies its body: + +```rust +assert(x != y); +``` + +The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. + +For more Noir syntax, check the [Language Concepts](@site/docs/explanations/noir/comments.md) chapter. + +## Build In/Output Files + +Change directory into _hello_world_ and build in/output files for your Noir program by running: + +```sh +cd hello_world +nargo check +``` + +Two additional files would be generated in your project directory: + +_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. + +## Prove Our Noir Program + +Now that the project is set up, we can create a proof of correct execution on our Noir program. + +Fill in input values for execution in the _Prover.toml_ file. For example: + +```toml +x = "1" +y = "2" +``` + +Prove the valid execution of your Noir program: + +```sh +nargo prove +``` + +A new folder _proofs_ would then be generated in your project directory, containing the proof file +`.proof`, where the project name is defined in Nargo.toml. + +The _Verifier.toml_ file would also be updated with the public values computed from program +execution (in this case the value of `y`): + +```toml +y = "0x0000000000000000000000000000000000000000000000000000000000000002" +``` + +> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. + +## Verify Our Noir Program + +Once a proof is generated, we can verify correct execution of our Noir program by verifying the +proof file. + +Verify your proof by running: + +```sh +nargo verify +``` + +The verification will complete in silence if it is successful. If it fails, it will log the +corresponding error instead. + +Congratulations, you have now created and verified a proof for your very first Noir program! + +In the [next section](@site/docs/getting_started/project_breakdown.md), we will go into more detail on each step performed. diff --git a/docs/docs/getting_started/installation/_category_.json b/docs/docs/getting_started/installation/_category_.json new file mode 100644 index 0000000000..0c02fb5d4d --- /dev/null +++ b/docs/docs/getting_started/installation/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 0, + "label": "Install Nargo", + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/getting_started/installation/index.md b/docs/docs/getting_started/installation/index.md new file mode 100644 index 0000000000..ddb8a250eb --- /dev/null +++ b/docs/docs/getting_started/installation/index.md @@ -0,0 +1,45 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo though the most common and easy method, noirup +keywords: [ + Nargo + Noir + Rust + Cargo + Noirup + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches + Noirup Repository +] +--- + +`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. + +With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. + +Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. + +## Installing Noirup + +Open a terminal on your machine, and write: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done. That's it. You should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. diff --git a/docs/docs/getting_started/installation/other_install_methods.md b/docs/docs/getting_started/installation/other_install_methods.md new file mode 100644 index 0000000000..d90a10103d --- /dev/null +++ b/docs/docs/getting_started/installation/other_install_methods.md @@ -0,0 +1,190 @@ +--- +title: Alternative Install Methods +description: + There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains other methods that don't rely on noirup, such as compiling from source, installing from binaries, and using WSL for windows +keywords: [ + Installation + Nargo + Noirup + Binaries + Compiling from Source + WSL for Windows + macOS + Linux + Nix + Direnv + Shell & editor experience + Building and testing + Uninstalling Nargo + Noir vs code extension +] +sidebar_position: 1 +--- + + +## Installation + +The most common method of installing Nargo is through [Noirup](@site/docs/getting_started/installation/index.md) + +However, there are other methods for installing Nargo: + +- [Binaries](#binaries) +- [Compiling from Source](#compile-from-source) +- [WSL for Windows](#wsl-for-windows) + +### Binaries + +See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous +platform specific binaries. + +#### Step 1 + +Paste and run the following in the terminal to extract and install the binary: + +> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend +> `sudo` and re-run it. + +##### macOS (Apple Silicon) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ +echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ +source ~/.zshrc +``` + +##### macOS (Intel) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ +echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ +source ~/.zshrc +``` + +##### Linux (Bash) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ +echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ +source ~/.bashrc +``` + +#### Step 2 + +Check if the installation was successful by running `nargo --version`. You should get a version number. + +> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from +> Finder. Close the new terminal popped up and `nargo` should now be accessible. + +### Option 3: Compile from Source + +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). + +Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. + +#### Setting up your environment + +For the best experience, please follow these instructions to setup your environment: + +1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. +2. Create the file `~/.config/nix/nix.conf` with the contents: + +```ini +experimental-features = nix-command +extra-experimental-features = flakes +``` + +3. Install direnv into your Nix profile by running: + +```sh +nix profile install nixpkgs#direnv +``` + +4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). + 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. +5. Restart your shell. + +#### Shell & editor experience + +Now that your environment is set up, you can get to work on the project. + +1. Clone the repository, such as: + +```sh +git clone git@github.com:noir-lang/noir +``` + +> Replacing `noir` with whichever repository you want to work on. + +2. Navigate to the directory: + +```sh +cd noir +``` + +> Replacing `noir` with whichever repository you cloned. + +3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: + +```sh +direnv allow +``` + +4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. + +5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): + +```sh +code . +``` + +6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. + +#### Building and testing + +Assuming you are using `direnv` to populate your environment, building and testing the project can be done +with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. + +If you want to build the entire project in an isolated sandbox, you can use Nix commands: + +1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. +2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. + +#### Without `direnv` + +If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. + +Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! + +### Option 4: WSL (for Windows) + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). + +Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. + +step 2: Follow the [Noirup instructions](@site/docs/getting_started/installation/index.md). + +## Uninstalling Nargo + +### Noirup + +If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` + +### Nix + +If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. + +```bash +rm ~/.nix-profile/bin/nargo +``` diff --git a/docs/docs/getting_started/project_breakdown.md b/docs/docs/getting_started/project_breakdown.md new file mode 100644 index 0000000000..026127b9ed --- /dev/null +++ b/docs/docs/getting_started/project_breakdown.md @@ -0,0 +1,199 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML + files, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] +sidebar_position: 2 +--- + +This section breaks down our hello world program in section _1.2_. We elaborate on the project +structure and what the `prove` and `verify` commands did in the previous section. + +## Anatomy of a Nargo Project + +Upon creating a new project with `nargo new` and building the in/output files with `nargo check` +commands, you would get a minimal Nargo project of the following structure: + + - src + - Prover.toml + - Verifier.toml + - Nargo.toml + +The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ +file will be generated within it. + +### Prover.toml + +_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. + +### Verifier.toml + +_Verifier.toml_ contains public in/output values computed when executing the Noir program. + +### Nargo.toml + +_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. + +Example Nargo.toml: + +```toml +[package] +name = "noirstarter" +type = "bin" +authors = ["Alice"] +compiler_version = "0.9.0" +description = "Getting started with Noir" +entry = "circuit/main.nr" +license = "MIT" + +[dependencies] +ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} +``` + +Nargo.toml for a [workspace](@site/docs/explanations/modules_packages_crates/workspaces.md) will look a bit different. For example: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +#### Package section + +The package section requires a number of fields including: + +- `name` (**required**) - the name of the package +- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract +- `authors` (optional) - authors of the project +- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) +- `description` (optional) +- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) +- `backend` (optional) +- `license` (optional) + +#### Dependencies section + +This is where you will specify any dependencies for your project. See the [Dependencies page](@site/docs/explanations/modules_packages_crates/dependencies.md) for more info. + +`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or +verifier contract respectively. + +### main.nr + +The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. + +In our sample program, _main.nr_ looks like this: + +```rust +fn main(x : Field, y : Field) { + assert(x != y); +} +``` + +The parameters `x` and `y` can be seen as the API for the program and must be supplied by the +prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when +verifying the proof. + +The prover supplies the values for `x` and `y` in the _Prover.toml_ file. + +As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is +constrained by the proof of the execution of said program (i.e. if the condition was not met, the +verifier would reject the proof as an invalid proof). + +### Prover.toml + +The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and +public). + +In our hello world program the _Prover.toml_ file looks like this: + +```toml +x = "1" +y = "2" +``` + +When the command `nargo prove` is executed, two processes happen: + +1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` + is not equal. This not equal constraint is due to the line `assert(x != y)`. + +2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. + +#### Arrays of Structs + +The following code shows how to pass an array of structs to a Noir program to generate a proof. + +```rust +// main.nr +struct Foo { + bar: Field, + baz: Field, +} + +fn main(foos: [Foo; 3]) -> pub Field { + foos[2].bar + foos[2].baz +} +``` + +Prover.toml: + +```toml +[[foos]] # foos[0] +bar = 0 +baz = 0 + +[[foos]] # foos[1] +bar = 0 +baz = 0 + +[[foos]] # foos[2] +bar = 1 +baz = 2 +``` + +#### Custom toml files + +You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. + +This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: + +```bash +nargo prove +``` + +This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: + +```bash +nargo prove -p OtherProver +``` + +## Verifying a Proof + +When the command `nargo verify` is executed, two processes happen: + +1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) + +2. If that file is found, the proof's validity is checked + +> **Note:** The validity of the proof is linked to the current Noir program; if the program is +> changed and the verifier verifies the proof, it will fail because the proof is not valid for the +> _modified_ Noir program. + +In production, the prover and the verifier are usually two separate entities. A prover would +retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the +verifier. The verifier would then retrieve the public inputs from usually external sources and +verifies the validity of the proof against it. + +Take a private asset transfer as an example: + +A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and +public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof +and submit it to the verifier smart contract. + +The verifier contract would then draw the user's encrypted balance directly from the blockchain and +verify the proof submitted against it. If the verification passes, additional functions in the +verifier contract could trigger (e.g. approve the asset transfer). + +Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/docs/docs/getting_started/tooling/_category_.json b/docs/docs/getting_started/tooling/_category_.json new file mode 100644 index 0000000000..dff520ebc4 --- /dev/null +++ b/docs/docs/getting_started/tooling/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 3, + "label": "Tooling", + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/getting_started/tooling/index.md b/docs/docs/getting_started/tooling/index.md new file mode 100644 index 0000000000..55df833005 --- /dev/null +++ b/docs/docs/getting_started/tooling/index.md @@ -0,0 +1,33 @@ +--- +title: Tooling +Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. +Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] +--- + +Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. + +## Playground + +The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). + +## IDE tools + +When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. + +The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +## Codespaces + +Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. + +## GitHub Actions + +You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as +installing `noirup` and running tests in your GitHub Action `yml` file. + +See the +[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. + +## Community projects + +As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/docs/docs/getting_started/tooling/language_server.md b/docs/docs/getting_started/tooling/language_server.md new file mode 100644 index 0000000000..81e0356ef8 --- /dev/null +++ b/docs/docs/getting_started/tooling/language_server.md @@ -0,0 +1,43 @@ +--- +title: Language Server +description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. +keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +sidebar_position: 0 +--- + +This section helps you install and configure the Noir Language Server. + +The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. + +## Language Server + +The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. +As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! + +If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. + +## Language Client + +The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. + +Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). +> +> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. + +When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: + +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) + +You should also see your tests in the `testing` panel: + +![Testing panel](@site/static/img/codelens_testing_panel.png) + +### Configuration + +- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. +- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. +- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. +- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/docs/getting_started/tooling/testing.md b/docs/docs/getting_started/tooling/testing.md new file mode 100644 index 0000000000..868a061200 --- /dev/null +++ b/docs/docs/getting_started/tooling/testing.md @@ -0,0 +1,62 @@ +--- +title: Testing in Noir +description: Learn how to use Nargo to test your Noir program in a quick and easy way +keywords: [Nargo, testing, Noir, compile, test] +sidebar_position: 1 +--- + +You can test your Noir programs using Noir circuits. + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. + +For example if you have a program like: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test] +fn test_add() { + assert(add(2,2) == 4); + assert(add(0,1) == 1); + assert(add(1,0) == 1); +} +``` + +Running `nargo test` will test that the `test_add` function can be executed while satisfying the all +the contraints which allows you to test that add returns the expected values. Test functions can't +have any arguments currently. + +### Test fail + +You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test(should_fail)] +fn test_add() { + assert(add(2,2) == 5); +} +``` + +You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: + +```rust +fn main(african_swallow_avg_speed : Field) { + assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); +} + +#[test] +fn test_king_arthur() { + main(65); +} + +#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] +fn test_bridgekeeper() { + main(32); +} + +``` diff --git a/docs/docs/how_to/03_solidity_verifier.md b/docs/docs/how_to/03_solidity_verifier.md new file mode 100644 index 0000000000..1a89fe492f --- /dev/null +++ b/docs/docs/how_to/03_solidity_verifier.md @@ -0,0 +1,129 @@ +--- +title: Generate a Solidity Verifier +description: + Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier + contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart + contract. Read more to find out! +keywords: + [ + solidity verifier, + smart contract, + blockchain, + compiler, + plonk_vk.sol, + EVM blockchain, + verifying Noir programs, + proving backend, + Barretenberg, + ] +--- + +For certain applications, it may be desirable to run the verifier as a smart contract instead of on +a local machine. + +Compile a Solidity verifier contract for your Noir program by running: + +```sh +nargo codegen-verifier +``` + +A new `contract` folder would then be generated in your project directory, containing the Solidity +file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. + +> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract +> platforms as long as the proving backend supplies an implementation. +> +> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in +> Solidity only for the time being. + +## Verify + +To verify a proof using the Solidity verifier contract, call the `verify` function with the +following signature: + +```solidity +function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) +``` + +You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): + +```solidity +function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { + // ... + bytes32[] memory publicInputs = new bytes32[](4); + publicInputs[0] = merkleRoot; + publicInputs[1] = bytes32(proposalId); + publicInputs[2] = bytes32(vote); + publicInputs[3] = nullifierHash; + require(verifier.verify(proof, publicInputs), "Invalid proof"); +``` + +### Public Inputs + +:::tip + +A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in +Noir. + +Under the hood, the return value is passed as an input to the circuit and is checked at the end of +the circuit program. + +::: + +The verifier contract uses the output (return) value of a Noir program as a public input. So if you +have the following function + +```rust +fn main( + // Public inputs + pubkey_x: pub Field, + pubkey_y: pub Field, + // Private inputs + priv_key: Field, +) -> pub Field +``` + +then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an +error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. + +In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. + +#### Struct inputs + +Consider the following program: + +```rust +struct Type1 { + val1: Field, + val2: Field, +} + +struct Nested { + t1: Type1, + is_true: bool, +} + +fn main(x: pub Field, nested: pub Nested, y: pub Field) { + //... +} +``` + +Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` + +## Noir for EVM chains + +You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: + +- Optimism +- Arbitrum +- Polygon PoS +- Scroll +- Celo + +Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. + +### Unsupported chains + +Unfortunately not all "EVM" chains are supported. + +**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/docs/docs/how_to/_category_.json b/docs/docs/how_to/_category_.json new file mode 100644 index 0000000000..23b560f610 --- /dev/null +++ b/docs/docs/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/how_to/merkle-proof.mdx b/docs/docs/how_to/merkle-proof.mdx new file mode 100644 index 0000000000..34074659ac --- /dev/null +++ b/docs/docs/how_to/merkle-proof.mdx @@ -0,0 +1,48 @@ +--- +title: Prove Merkle Tree Membership +description: + Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a + merkle tree with a specified root, at a given index. +keywords: + [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +--- + +Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is +in a merkle tree. + +```rust +use dep::std; + +fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { + let leaf = std::hash::hash_to_field(message); + let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); + assert(merkle_root == root); +} + +``` + +The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen +by the backend. The only requirement is that this hash function can heuristically be used as a +random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` +instead. + +```rust +let leaf = std::hash::hash_to_field(message); +``` + +The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. + +```rust +let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); +assert (merkle_root == root); +``` + +> **Note:** It is possible to re-implement the merkle tree implementation without standard library. +> However, for most usecases, it is enough. In general, the standard library will always opt to be +> as conservative as possible, while striking a balance with efficiency. + +An example, the merkle membership proof, only requires a hash function that has collision +resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient +than the even more conservative sha256. + +[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/docs/index.md b/docs/docs/index.md index 75e1abf293..754f9f6e31 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -1,9 +1,8 @@ --- -title: Introducing Noir +title: Noir description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. + Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to + an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. keywords: [ Noir, @@ -18,83 +17,69 @@ keywords: Proving System, Smart Contract Language, ] -slug: / +sidebar_position: 0 --- -## What is Noir? +## What's new about Noir? -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. +Noir, a domain-specific language crafted for SNARK proving systems, stands out with its simplicity, flexibility, +and robust capabilities. Unlike conventional approaches that compile directly to a fixed NP-complete language, +Noir takes a two-pronged path. It first compiles to an adaptable intermediate language known as ACIR. From there, +depending on the project's needs, ACIR can be further compiled into an arithmetic circuit for integration with Aztec's +barretenberg backend or transformed into a rank-1 constraint system suitable for R1CS backends like Arkwork's Marlin +backend, among others. -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. +This innovative design introduces unique challenges, yet it strategically separates the programming language from the +backend. Noir's approach echoes the modular philosophy of LLVM, offering developers a versatile toolkit for cryptographic +programming. ## Who is Noir for? -Noir can be used for a variety of purposes. - ### Solidity Developers -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create -a verifier contract. +Noir streamlines the creation of Solidity contracts that interface with SNARK systems. +[`Utilize the nargo codegen-verifier`](@site/docs/reference/nargo_commands.md#nargo-codegen-verifier) command to construct verifier +contracts efficiently. While the current alpha version offers this as a direct feature, future updates aim +to modularize this process for even greater ease of use. + +Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will be +modularised in the future; however, as of the alpha, you can use the + command to create a verifier contract. ### Protocol Developers -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. +Should the Aztec backend not align with your existing tech stack, or if you're inclined to integrate alternative +proving systems, Noir's agnostic compilation to a proof-agnostic intermediate language offers unmatched flexibility. +This allows protocol engineers the freedom to substitute the default PLONK-based system with an alternative of their +choice, tailoring the proving system to their specific needs. ### Blockchain developers -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen Commitment -- Pedersen Hash -- HashToField +Blockchain developers often face environmental constraints, such as predetermined proving systems and smart contract +languages. Noir addresses this by enabling the implementation of custom proving system backends and smart contract +interfaces, ensuring seamless integration with your blockchain's architecture, and expanding the horizons for innovation +within your projects. ## Libraries -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). +Noir does not currently have an official package manager. You can find a list of available Noir libraries in the +[awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). Some libraries that are available today include: - [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains + the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage + proof verification (or verification of any trie proof involving 32-byte long keys) +- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing + for computations on large unsigned integers +- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and + return the source Ethereum address +- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of + sparse Merkle trees +- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data + type, allowing access to negative numbers on Noir +- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, + allowing results that aren't whole numbers + +See the section on [dependencies](@site/docs/explanations/modules_packages_crates/dependencies.md) for more information. diff --git a/docs/docs/language_concepts/01_functions.md b/docs/docs/language_concepts/01_functions.md deleted file mode 100644 index 47cdea0cf0..0000000000 --- a/docs/docs/language_concepts/01_functions.md +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: - -```rust -pub fn foo() {} -``` - -You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: - -```rust -pub(crate) fn foo() {} //foo can only be called within its crate -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : pub Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : pub Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Main function - -If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: - -```rust -fn main(x : Field) // this is fine: passing a Field -fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time -fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 -fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 - -fn main(x : Vec) // can't compile, has variable size -fn main(x : [Field]) // can't compile, has variable size -fn main(....// i think you got it by now -``` - -Keep in mind [tests](../nargo/02_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: - -```rust -fn main(x : [Field]) { - assert(x[0] == 1); -} - -#[test] -fn test_one() { - main([1, 2]); -} -``` - -```bash -$ nargo test -[testing] Running 1 test functions -[testing] Testing test_one... ok -[testing] All tests passed - -$ nargo check -The application panicked (crashed). -Message: Cannot have variable sized arrays as a parameter to main -``` - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -It is also possible to specialize which method is chosen depending on the [generic](./06_generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: - -```rust -struct Foo {} - -impl Foo { - fn foo(self) -> Field { 1 } -} - -impl Foo { - fn foo(self) -> Field { 2 } -} - -fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; - assert(f1.foo() + f2.foo() == 3); -} -``` - -Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. - -```rust -// Including this impl in the same project as the above snippet would -// cause an overlapping impls error -impl Foo { - fn foo(self) -> Field { 3 } -} -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./08_lambdas.md) for more details. - -## Attributes - -Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. - -Supported attributes include: - -- **builtin**: the function is implemented by the compiler, for efficiency purposes. -- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` -- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details -- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](../noir_js/noir_js.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../nargo/02_testing.md) for more details - -### Field Attribute - -The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. -The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. -As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. - -Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. - -```rust -#[field(bn254)] -fn foo() -> u32 { - 1 -} - -#[field(23)] -fn foo() -> u32 { - 2 -} - -// This commented code would not compile as foo would be defined twice because it is the same field as bn254 -// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] -// fn foo() -> u32 { -// 2 -// } - -#[field(bls12_381)] -fn foo() -> u32 { - 3 -} -``` - -If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/docs/docs/language_concepts/03_ops.md b/docs/docs/language_concepts/03_ops.md deleted file mode 100644 index da02b12605..0000000000 --- a/docs/docs/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/docs/docs/language_concepts/07_mutability.md b/docs/docs/language_concepts/07_mutability.md deleted file mode 100644 index 4641521b1d..0000000000 --- a/docs/docs/language_concepts/07_mutability.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -:::warning - -The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. - -::: - -## Globals - -Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * mysubmodule::N; - assert(res != res2); -} - -mod mysubmodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/docs/language_concepts/data_types/00_fields.md b/docs/docs/language_concepts/data_types/00_fields.md deleted file mode 100644 index 658a0441ff..0000000000 --- a/docs/docs/language_concepts/data_types/00_fields.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index e87eb1feab..a5fd10769f 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -16,7 +16,7 @@ To update, please make sure this field in `Nargo.toml` matches the output of `na ## ≥0.14 -The index of the [for loops](./language_concepts/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: +The index of the [for loops](@site/docs/explanations/noir/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: ```rust for i in 0..10 { @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running this bash script: , where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/.nojekyll b/docs/docs/reference/NoirJS/backend_barretenberg/.nojekyll new file mode 100644 index 0000000000..e2ac6616ad --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/docs/docs/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 0000000000..5cbe9421b9 --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,185 @@ +# BarretenbergBackend + +## Implements + +- [`Backend`](../interfaces/Backend.md) + +## Constructors + +### new BarretenbergBackend(acirCircuit, options) + +```ts +new BarretenbergBackend(acirCircuit, options): BarretenbergBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergBackend`](BarretenbergBackend.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(witness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `witness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) + +#### Example + +```typescript +const intermediateProof = await backend.generateIntermediateProof(witness); +``` + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) + +#### Example + +```typescript +const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) + +#### Example + +```typescript +const isValidIntermediate = await backend.verifyIntermediateProof(proof); +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/index.md b/docs/docs/reference/NoirJS/backend_barretenberg/index.md new file mode 100644 index 0000000000..bfbecb5286 --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/index.md @@ -0,0 +1,45 @@ +# backend_barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | + +### Interfaces + +| Interface | Description | +| :------ | :------ | +| [Backend](interfaces/Backend.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | + +## Functions + +### flattenPublicInputs() + +```ts +flattenPublicInputs(publicInputs): string[] +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `publicInputs` | `WitnessMap` | + +#### Returns + +`string`[] + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/interfaces/Backend.md b/docs/docs/reference/NoirJS/backend_barretenberg/interfaces/Backend.md new file mode 100644 index 0000000000..3eb9645c8d --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/interfaces/Backend.md @@ -0,0 +1,132 @@ +# Backend + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates an intermediate proof (meant to be verified in another circuit) + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | +| `numOfPublicInputs` | `number` | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Retrieves the artifacts from a proof in the Field format + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies an intermediate proof + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 0000000000..266ade75d1 --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,19 @@ +# BackendOptions + +```ts +type BackendOptions: object; +``` + +## Description + +An options object, currently only used to specify the number of threads to use. + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `threads` | `number` | **Description**

Number of threads | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md new file mode 100644 index 0000000000..34e0dd0420 --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

ABI representation of the circuit | +| `bytecode` | `string` | **Description**

The bytecode of the circuit | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md new file mode 100644 index 0000000000..3eb360a78f --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/type-aliases/ProofData.md @@ -0,0 +1,20 @@ +# ProofData + +```ts +type ProofData: object; +``` + +## Description + +The representation of a proof + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | +| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/docs/docs/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 0000000000..2aaa55bccf --- /dev/null +++ b/docs/docs/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/docs/reference/NoirJS/noir_js/.nojekyll b/docs/docs/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 0000000000..e2ac6616ad --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/docs/reference/NoirJS/noir_js/classes/Noir.md b/docs/docs/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 0000000000..34e20d9968 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,132 @@ +# Noir + +## Constructors + +### new Noir(circuit, backend) + +```ts +new Noir(circuit, backend?): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `backend`? | `Backend` | + +#### Returns + +[`Noir`](Noir.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the underlying backend instance. + +#### Example + +```typescript +await noir.destroy(); +``` + +*** + +### execute() + +```ts +execute(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Allows to execute a circuit to get its witness and return value. + +#### Example + +```typescript +async execute(inputs) +``` + +*** + +### generateFinalProof() + +```ts +generateFinalProof(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a witness and a proof given an object as input. + +#### Example + +```typescript +async generateFinalProof(input) +``` + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Instantiates the verification key and verifies a proof. + +#### Example + +```typescript +async verifyFinalProof(proof) +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/and.md b/docs/docs/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 0000000000..c783283e39 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/blake2s256.md b/docs/docs/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 0000000000..7882d0da8d --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 0000000000..0ba5783f0d --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,29 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. +Verifies a ECDSA signature over the secp256k1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 0000000000..0b20ff6895 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/keccak256.md b/docs/docs/reference/NoirJS/noir_js/functions/keccak256.md new file mode 100644 index 0000000000..d10f155ce8 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/sha256.md b/docs/docs/reference/NoirJS/noir_js/functions/sha256.md new file mode 100644 index 0000000000..6ba4ecac02 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/functions/xor.md b/docs/docs/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 0000000000..8d762b895d --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/index.md b/docs/docs/reference/NoirJS/noir_js/index.md new file mode 100644 index 0000000000..8b9e35bc9a --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/index.md @@ -0,0 +1,37 @@ +# noir_js + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | +| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | +| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | +| [InputMap](type-aliases/InputMap.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | +| [WitnessMap](type-aliases/WitnessMap.md) | - | + +### Functions + +| Function | Description | +| :------ | :------ | +| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | +| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | +| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | +| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | +| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | +| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | +| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md new file mode 100644 index 0000000000..34e0dd0420 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

ABI representation of the circuit | +| `bytecode` | `string` | **Description**

The bytecode of the circuit | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 0000000000..812b8b1648 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# ForeignCallHandler + +```ts +type ForeignCallHandler: (name, inputs) => Promise; +``` + +A callback which performs an foreign call and returns the response. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | The identifier for the type of foreign call being performed. | +| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | + +## Returns + +`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> + +outputs - An array of hex encoded outputs containing the results of the foreign call. + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 0000000000..dd95809186 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# ForeignCallInput + +```ts +type ForeignCallInput: string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 0000000000..b71fb78a94 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# ForeignCallOutput + +```ts +type ForeignCallOutput: string | string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/InputMap.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/InputMap.md new file mode 100644 index 0000000000..c714e999d9 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/InputMap.md @@ -0,0 +1,13 @@ +# InputMap + +```ts +type InputMap: object; +``` + +## Index signature + + \[`key`: `string`\]: `InputValue` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md new file mode 100644 index 0000000000..3eb360a78f --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/ProofData.md @@ -0,0 +1,20 @@ +# ProofData + +```ts +type ProofData: object; +``` + +## Description + +The representation of a proof + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | +| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/docs/docs/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 0000000000..258c46f9d0 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/docs/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/docs/docs/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 0000000000..fe2629ddc9 --- /dev/null +++ b/docs/docs/reference/NoirJS/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/InputMap","label":"InputMap"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/docs/reference/_category_.json b/docs/docs/reference/_category_.json new file mode 100644 index 0000000000..5b6a20a609 --- /dev/null +++ b/docs/docs/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/docs/docs/reference/nargo_commands.md b/docs/docs/reference/nargo_commands.md new file mode 100644 index 0000000000..239e88d969 --- /dev/null +++ b/docs/docs/reference/nargo_commands.md @@ -0,0 +1,250 @@ +--- +title: Nargo +description: + Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, + generate Solidity verifier smart contract and compile into JSON file containing ACIR + representation and ABI of circuit. +keywords: + [ + Nargo, + Noir CLI, + Noir Prover, + Noir Verifier, + generate Solidity verifier, + compile JSON file, + ACIR representation, + ABI of circuit, + TypeScript, + ] +sidebar_position: 0 +--- + +## General options + +| Option | Description | +| -------------------- | -------------------------------------------------- | +| `--show-ssa` | Emit debug information for the intermediate SSA IR | +| `--deny-warnings` | Quit execution when warnings are emitted | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo help [subcommand]` + +Prints the list of available commands or specific information of a subcommand. + +_Arguments_ + +| Argument | Description | +| -------------- | -------------------------------------------- | +| `` | The subcommand whose help message to display | + +## `nargo backend` + +Installs and selects custom backends used to generate and verify proofs. + +### Commands + +| Command | Description | +| ----------- | --------------------------------------------------------- | +| `current` | Prints the name of the currently active backend | +| `ls` | Prints the list of currently installed backends | +| `use` | Select the backend to use | +| `install` | Install a new backend from a URL | +| `uninstall` | Uninstalls a backend | +| `help` | Print this message or the help of the given subcommand(s) | + +### Options + +| Option | Description | +| ------------ | ----------- | +| `-h, --help` | Print help | + +## `nargo check` + +Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output +values of the Noir program respectively. + +### Options + +| Option | Description | +| --------------------- | ------------------------------------- | +| `--package ` | The name of the package to check | +| `--workspace` | Check all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +### `nargo codegen-verifier` + +Generate a Solidity verifier smart contract for the program. + +### Options + +| Option | Description | +| --------------------- | ------------------------------------- | +| `--package ` | The name of the package to codegen | +| `--workspace` | Codegen all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo compile` + +Compile the program into a JSON build artifact file containing the ACIR representation and the ABI +of the circuit. This build artifact can then be used to generate and verify proofs. + +You can also use "build" as an alias for compile (e.g. `nargo build`). + +### Options + +| Option | Description | +| --------------------- | ------------------------------------------------------------ | +| `--package ` | The name of the package to compile | +| `--workspace` | Compile all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo new ` + +Creates a new Noir project in a new folder. + +**Arguments** + +| Argument | Description | +| -------- | -------------------------------- | +| `` | The path to save the new project | + +### Options + +| Option | Description | +| --------------- | ----------------------------------------------------- | +| `--name ` | Name of the package [default: package directory name] | +| `--lib` | Use a library template | +| `--bin` | Use a binary template [default] | +| `--contract` | Use a contract template | +| `-h, --help` | Print help | + +## `nargo init` + +Creates a new Noir project in the current directory. + +### Options + +| Option | Description | +| --------------- | ----------------------------------------------------- | +| `--name ` | Name of the package [default: current directory name] | +| `--lib` | Use a library template | +| `--bin` | Use a binary template [default] | +| `--contract` | Use a contract template | +| `-h, --help` | Print help | + +## `nargo execute [WITNESS_NAME]` + +Runs the Noir program and prints its return value. + +**Arguments** + +| Argument | Description | +| ---------------- | ----------------------------------------- | +| `[WITNESS_NAME]` | Write the execution witness to named file | + +### Options + +| Option | Description | +| --------------------------------- | ------------------------------------------------------------------------------------ | +| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | +| `--package ` | The name of the package to execute | +| `--workspace` | Execute all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +_Usage_ + +The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which +must be filled in. + +To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A +`.tr` file will then be saved in the `./target` folder. + +## `nargo prove` + +Creates a proof for the program. + +### Options + +| Option | Description | +| ------------------------------------- | ---------------------------------------------------------------------------------------- | +| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | +| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | +| `--verify` | Verify proof after proving | +| `--package ` | The name of the package to prove | +| `--workspace` | Prove all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo verify` + +Given a proof and a program, verify whether the proof is valid. + +### Options + +| Option | Description | +| ------------------------------------- | ---------------------------------------------------------------------------------------- | +| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | +| `--package ` | The name of the package to verify | +| `--workspace` | Verify all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo test [TEST_NAME]` + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. + +Takes an optional `--exact` flag which allows you to select tests based on an exact name. + +See an example on the [testing page](@site/docs/getting_started/tooling/testing.md). + +### Options + +| Option | Description | +| --------------------- | -------------------------------------- | +| `--show-output` | Display output of `println` statements | +| `--exact` | Only run tests that match exactly | +| `--package ` | The name of the package to test | +| `--workspace` | Test all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo info` + +Prints a table containing the information of the package. + +Currently the table provide + +1. The number of ACIR opcodes +2. The final number gates in the circuit used by a backend + +If the file contains a contract the table will provide the +above information about each function of the contract. + +## `nargo lsp` + +Start a long-running Language Server process that communicates over stdin/stdout. +Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). + +## `nargo fmt` + +Automatically formats your Noir source code based on the default formatting settings. diff --git a/docs/docs/tutorials/noirjs_app.md b/docs/docs/tutorials/noirjs_app.md new file mode 100644 index 0000000000..e0f674fa09 --- /dev/null +++ b/docs/docs/tutorials/noirjs_app.md @@ -0,0 +1,261 @@ +--- +title: Tiny NoirJS app +description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment +keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] +sidebar_position: 0 +--- + +NoirJS works both on the browser and on the server, and works for both ESM and CJS module systems. In this page, we will learn how can we write a simple test and a simple web app to verify the standard Noir example. + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Before we start + +:::note + +Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.18.x matches `noir_js@0.18.x`, etc. + +In this guide, we will be pinned to 0.17.0. + +::: + +Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). + +First of all, follow the the [Nargo guide](@site/docs/getting_started/installation/index.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: + +```bash +nargo compile +``` + +Your folder structure should look like: + +```tree +. +└── circuit + ├── Nargo.toml + ├── src + │ └── main.nr + └── target + └── circuit.json +``` + +## Starting a new project + +Go back to the previous folder and start a new project by running run `npm init`. You can configure your project or just leave the defaults, and see a `package.json` appear in your root folder. + +## Installing dependencies + +We'll need two `npm` packages. These packages will provide us the methods we need to run and verify proofs: + +```bash +npm i @noir-lang/backend_barretenberg@^0.17.0 @noir-lang/noir_js@^0.17.0 +``` + +To serve our page, we can use a build tool such as `vite`. Because we're gonna use some `wasm` files, we need to install a plugin as well. Run: + +```bash +npm i --save-dev vite rollup-plugin-copy +``` + +Since we're on the dependency world, we may as well define a nice starting script. Vite makes it easy. Just open `package.json`, find the block "scripts" and add this just below the line with `"test" : "echo......."`: + +```json + "start": "vite --open" +``` + +If you want do build a static website, you can also add some build and preview scripts: + +```json + "build": "vite build", + "preview": "vite preview" +``` + +## Vite plugins + +Vite is great, but support from `wasm` doesn't work out-of-the-box. We're gonna write a quick plugin and use another one. Just copy and paste this into a file named `vite.config.js`. You don't need to understand it, just trust me bro. + +```js +import { defineConfig } from 'vite'; +import copy from 'rollup-plugin-copy'; +import fs from 'fs'; +import path from 'path'; + +const wasmContentTypePlugin = { + name: 'wasm-content-type-plugin', + configureServer(server) { + server.middlewares.use(async (req, res, next) => { + if (req.url.endsWith('.wasm')) { + res.setHeader('Content-Type', 'application/wasm'); + const newPath = req.url.replace('deps', 'dist'); + const targetPath = path.join(__dirname, newPath); + const wasmContent = fs.readFileSync(targetPath); + return res.end(wasmContent); + } + next(); + }); + }, +}; + +export default defineConfig(({ command }) => { + if (command === 'serve') { + return { + plugins: [ + copy({ + targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], + copySync: true, + hook: 'buildStart', + }), + command === 'serve' ? wasmContentTypePlugin : [], + ], + }; + } + + return {}; +}); +``` + +## HTML + +Here's the simplest HTML with some terrible UI. Create a file called `index.html` and paste this: + +```html + + + + + + +

Very basic Noir app

+
+

Logs

+

Proof

+
+ + +``` + +## Some good old vanilla Javascript + +Create a new file `app.js`, which is where our javascript code will live. Let's start with this code inside: + +```js +document.addEventListener('DOMContentLoaded', async () => { + // here's where the magic happens +}); + +function display(container, msg) { + const c = document.getElementById(container); + const p = document.createElement('p'); + p.textContent = msg; + c.appendChild(p); +} +``` + +We can manipulate our website with this little function, so we can see our website working. + +## Adding Noir + +If you come from the previous page, your folder structure should look like this: + +```tree +├── app.js +├── circuit +│ ├── Nargo.toml +│ ├── src +│ │ └── main.nr +│ └── target +│ └── circuit.json +├── index.html +├── package.json +└── vite.config.js +``` + +You'll see other files and folders showing up (like `package-lock.json`, `yarn.lock`, `node_modules`) but you shouldn't have to care about those. + +## Importing our dependencies + +We're starting with the good stuff now. At the top of the new javascript file, import the packages: + +```ts +import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; +``` + +We also need to import the `circuit` JSON file we created. If you have the suggested folder structure, you can add this line: + +```ts +import circuit from './circuit/target/circuit.json'; +``` + +## Write code + +:::note + +We're gonna be adding code inside the `document.addEventListener...etc` block: + +```js +// forget stuff here +document.addEventListener('DOMContentLoaded', async () => { + // here's where the magic happens +}); +// forget stuff here +``` + +::: + +Our dependencies exported two classes: `BarretenbergBackend` and `Noir`. Let's `init` them and add some logs, just to flex: + +```ts +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit, backend); +``` + +## Proving + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +const input = { x: 1, y: 2 }; +display('logs', 'Generating proof... ⌛'); +const proof = await noir.generateFinalProof(input); +display('logs', 'Generating proof... ✅'); +display('results', proof.proof); +``` + +You're probably eager to see stuff happening, so go and run your app now! + +From your terminal, run `npm start` (or `yarn start`). If it doesn't open a browser for you, just visit `localhost:5173`. On a modern laptop, proof will generate in less than 100ms, and you'll see this: + +![Getting Started 0](@site/static/img/noir_getting_started_1.png) + +If you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human. + +In any case, this means your proof was generated! But you shouldn't trust me just yet. Add these lines to see it being verified: + +```js +display('logs', 'Verifying proof... ⌛'); +const verification = await noir.verifyFinalProof(proof); +if (verification) display('logs', 'Verifying proof... ✅'); +``` + +By saving, your app will refresh and here's our complete Tiny Noir App! + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Further Reading + +You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/next-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. + +You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js deleted file mode 100644 index 8f62df3d0e..0000000000 --- a/docs/docusaurus.config.js +++ /dev/null @@ -1,215 +0,0 @@ -// @ts-check -// Note: type annotations allow type checking and IDEs autocompletion - -const lightCodeTheme = require('prism-react-renderer/themes/github'); -const darkCodeTheme = require('prism-react-renderer/themes/dracula'); - -const math = require('remark-math'); -const katex = require('rehype-katex'); - -/** @type {import('@docusaurus/types').Config} */ -const config = { - title: 'Noir Documentation', - tagline: 'The Universal ZK Circuit Language', - favicon: 'img/favicon.ico', - url: 'https://noir-lang.org', - // Set the // pathname under which your site is served - // For GitHub pages deployment, it is often '//' - baseUrl: '/', - onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'throw', - - // Even if you don't use internalization, you can use this field to set useful - // metadata like html lang. For example, if your site is Chinese, you may want - // to replace "en" with "zh-Hans". - i18n: { - defaultLocale: 'en', - locales: ['en'], - }, - - presets: [ - [ - '@docusaurus/preset-classic', - { - // gtag: { - // trackingID: 'G-SZQHEQZK3L', - // anonymizeIP: true, - // }, - docs: { - sidebarPath: require.resolve('./sidebars.js'), - routeBasePath: '/', - remarkPlugins: [math], - rehypePlugins: [katex], - versions: { - current: { - label: 'dev', - path: 'dev', - }, - }, - editUrl: ({ versionDocsDirPath, docPath }) => - `https://github.com/noir-lang/noir/edit/master/docs/${versionDocsDirPath}/${docPath}`, - }, - blog: false, - theme: { - customCss: require.resolve('./src/css/custom.css'), - }, - }, - ], - ], - - themeConfig: - /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ - { - // Replace with your project's social card - navbar: { - logo: { - alt: 'Noir Logo', - src: 'img/logo.svg', - srcDark: 'img/logoDark.svg', - href: '/', - }, - items: [ - { - href: 'https://github.com/noir-lang/docs', - label: 'GitHub', - position: 'right', - }, - { - type: 'docsVersionDropdown', - position: 'left', - dropdownActiveClassDisabled: true, - }, - ], - }, - metadata: [ - { - name: 'Noir', - content: 'noir, programming, language, documentation, zk, zero-knowledge, l2, crypto, layer2, ethereum', - }, - ], - footer: { - style: 'dark', - links: [ - { - title: 'Community', - items: [ - { - label: 'Noir Forum', - href: 'https://discourse.aztec.network/c/noir/7', - }, - { - label: 'Twitter', - href: 'https://twitter.com/NoirLang', - }, - { - label: 'Discord', - href: 'https://discord.gg/JtqzkdeQ6G', - }, - ], - }, - { - title: 'Code', - items: [ - { - label: 'Noir GitHub', - href: 'https://github.com/noir-lang', - }, - { - label: 'Docs GitHub', - href: 'https://github.com/noir-lang/docs', - }, - ], - }, - ], - copyright: `Noir will be dual licensed under MIT/Apache (Version 2.0).`, - }, - prism: { - theme: lightCodeTheme, - darkTheme: darkCodeTheme, - additionalLanguages: ['rust', 'powershell', 'solidity', 'toml'], - }, - stylesheets: [ - { - href: 'https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css', - type: 'text/css', - integrity: 'sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM', - crossorigin: 'anonymous', - }, - ], - algolia: { - // The application ID provided by Algolia - appId: '97APAVUL6H', - - // Public API key: it is safe to commit it - apiKey: 'b9b94d2f1c58f7d509f0bc1f13b381fb', - - indexName: 'noir-lang', - }, - }, - plugins: [ - [ - 'docusaurus-plugin-typedoc', - { - id: 'noir_js', - entryPoints: ['../tooling/noir_js/src/index.ts'], - tsconfig: '../tooling/noir_js/tsconfig.json', - entryPointStrategy: 'resolve', - out: 'docs/noir_js/reference/noir_js', - plugin: ['typedoc-plugin-markdown'], - name: 'Noir JS', - disableSources: true, - excludePrivate: true, - - sidebar: { - filteredIds: ['noir_js/reference/noir_js/index'], - }, - readme: 'none', - hidePageHeader: true, - hideBreadcrumbs: true, - hideInPageTOC: true, - useCodeBlocks: true, - typeDeclarationFormat: 'table', - propertiesFormat: 'table', - parametersFormat: 'table', - enumMembersFormat: 'table', - indexFormat: 'table', - outputFileStrategy: 'members', - memberPageTitle: '{name}', - membersWithOwnFile: ['Interface', 'Class', 'TypeAlias', 'Function'], - }, - ], - [ - 'docusaurus-plugin-typedoc', - { - id: 'noir_js_backend_barretenberg', - entryPoints: ['../tooling/noir_js_backend_barretenberg/src/index.ts'], - tsconfig: '../tooling/noir_js_backend_barretenberg/tsconfig.json', - entryPointStrategy: 'resolve', - out: 'docs/noir_js/reference/backend_barretenberg', - plugin: ['typedoc-plugin-markdown'], - name: 'Backend Barretenberg', - disableSources: true, - excludePrivate: true, - - sidebar: { - filteredIds: ['noir_js/reference/backend_barretenberg/index'], - }, - readme: 'none', - hidePageHeader: true, - hideBreadcrumbs: true, - hideInPageTOC: true, - useCodeBlocks: true, - typeDeclarationFormat: 'table', - propertiesFormat: 'table', - parametersFormat: 'table', - enumMembersFormat: 'table', - indexFormat: 'table', - outputFileStrategy: 'members', - memberPageTitle: '{name}', - membersWithOwnFile: ['Interface', 'Class', 'TypeAlias'], - }, - ], - ], -}; - -module.exports = config; diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts new file mode 100644 index 0000000000..98ef1fd680 --- /dev/null +++ b/docs/docusaurus.config.ts @@ -0,0 +1,212 @@ +import type { Config } from '@docusaurus/types'; + +const { themes } = require('prism-react-renderer'); +const lightTheme = themes.github; +const darkTheme = themes.dracula; + +import math from 'remark-math'; +import katex from 'rehype-katex'; + +export default { + title: 'Noir Documentation', + tagline: 'The Universal ZK Circuit Language', + favicon: 'img/favicon.ico', + url: 'https://noir-lang.org', + baseUrl: '/', + onBrokenLinks: 'throw', + onBrokenMarkdownLinks: 'throw', + i18n: { + defaultLocale: 'en', + locales: ['en'], + }, + + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + sidebarPath: './sidebars.js', + routeBasePath: '/docs', + remarkPlugins: [math], + rehypePlugins: [katex], + versions: { + current: { + label: 'dev', + path: 'dev', + }, + }, + editUrl: ({ versionDocsDirPath, docPath }) => + `https://github.com/noir-lang/noir/edit/master/docs/${versionDocsDirPath}/${docPath}`, + }, + blog: false, + theme: { + customCss: './src/css/custom.css', + }, + }, + ], + ], + + themeConfig: { + navbar: { + logo: { + alt: 'Noir Logo', + src: 'img/logo.svg', + srcDark: 'img/logoDark.svg', + href: '/', + }, + items: [ + { + href: 'https://github.com/noir-lang/noir/tree/master/docs', + label: 'GitHub', + position: 'right', + }, + { + type: 'docsVersionDropdown', + position: 'left', + dropdownActiveClassDisabled: true, + }, + ], + }, + metadata: [ + { + name: 'Noir', + content: 'noir, programming, language, documentation, zk, zero-knowledge, l2, crypto, layer2, ethereum', + }, + ], + footer: { + style: 'dark', + links: [ + { + title: 'Community', + items: [ + { + label: 'Noir Forum', + href: 'https://discourse.aztec.network/c/noir/7', + }, + { + label: 'Twitter', + href: 'https://twitter.com/NoirLang', + }, + { + label: 'Discord', + href: 'https://discord.gg/JtqzkdeQ6G', + }, + ], + }, + { + title: 'Code', + items: [ + { + label: 'Noir GitHub', + href: 'https://github.com/noir-lang', + }, + { + label: 'Docs GitHub', + href: 'https://github.com/noir-lang/docs', + }, + ], + }, + ], + copyright: `Noir will be dual licensed under MIT/Apache (Version 2.0).`, + }, + prism: { + theme: lightTheme, + darkTheme: darkTheme, + additionalLanguages: ['rust', 'powershell', 'solidity', 'toml'], + }, + stylesheets: [ + { + href: 'https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css', + type: 'text/css', + integrity: 'sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM', + crossorigin: 'anonymous', + }, + ], + algolia: { + // The application ID provided by Algolia + appId: '97APAVUL6H', + + // Public API key: it is safe to commit it + apiKey: 'b9b94d2f1c58f7d509f0bc1f13b381fb', + + indexName: 'noir-lang', + }, + }, + plugins: [ + () => ({ + name: 'resolve-react', + configureWebpack() { + return { + optimization: { + innerGraph: false, + }, + }; + }, + }), + [ + 'docusaurus-plugin-typedoc', + { + id: 'noir_js', + entryPoints: ['../tooling/noir_js/src/index.ts'], + tsconfig: '../tooling/noir_js/tsconfig.json', + entryPointStrategy: 'resolve', + out: 'docs/reference/NoirJS/noir_js', + plugin: ['typedoc-plugin-markdown'], + name: 'noir_js', + disableSources: true, + excludePrivate: true, + skipErrorChecking: true, + sidebar: { + filteredIds: ['reference/NoirJS/noir_js/index'], + }, + readme: 'none', + hidePageHeader: true, + hideBreadcrumbs: true, + hideInPageTOC: true, + useCodeBlocks: true, + typeDeclarationFormat: 'table', + propertiesFormat: 'table', + parametersFormat: 'table', + enumMembersFormat: 'table', + indexFormat: 'table', + outputFileStrategy: 'members', + memberPageTitle: '{name}', + membersWithOwnFile: ['Interface', 'Class', 'TypeAlias', 'Function'], + }, + ], + [ + 'docusaurus-plugin-typedoc', + { + id: 'noir_js_backend_barretenberg', + entryPoints: ['../tooling/noir_js_backend_barretenberg/src/index.ts'], + tsconfig: '../tooling/noir_js_backend_barretenberg/tsconfig.json', + entryPointStrategy: 'resolve', + out: 'docs/reference/NoirJS/backend_barretenberg', + plugin: ['typedoc-plugin-markdown'], + name: 'backend_barretenberg', + disableSources: true, + excludePrivate: true, + skipErrorChecking: true, + sidebar: { + filteredIds: ['reference/NoirJS/backend_barretenberg/index'], + }, + readme: 'none', + hidePageHeader: true, + hideBreadcrumbs: true, + hideInPageTOC: true, + useCodeBlocks: true, + typeDeclarationFormat: 'table', + propertiesFormat: 'table', + parametersFormat: 'table', + enumMembersFormat: 'table', + indexFormat: 'table', + outputFileStrategy: 'members', + memberPageTitle: '{name}', + membersWithOwnFile: ['Interface', 'Class', 'TypeAlias'], + }, + ], + ], + markdown: { + format: 'detect', + }, +} satisfies Config; diff --git a/docs/package.json b/docs/package.json index 09f8d718b5..86f15b0a31 100644 --- a/docs/package.json +++ b/docs/package.json @@ -4,32 +4,44 @@ "private": true, "scripts": { "start": "docusaurus start", - "build": "docusaurus build", - "setStable": "node ./scripts/setStable.js" + "build": "yarn version::stables && docusaurus build", + "version::stables": "node --loader ts-node/esm ./scripts/setStable.ts", + "serve": "serve build" }, "dependencies": { - "@docusaurus/core": "^2.4.0", - "@docusaurus/plugin-google-gtag": "^2.4.0", - "@docusaurus/preset-classic": "^2.4.0", + "@docusaurus/core": "^3.0.1", + "@docusaurus/preset-classic": "^3.0.1", "@easyops-cn/docusaurus-search-local": "^0.35.0", - "@mdx-js/react": "^1.6.22", + "@mdx-js/react": "^3.0.0", + "@noir-lang/noir_js": "workspace:*", + "@noir-lang/noirc_abi": "workspace:*", + "@noir-lang/types": "workspace:*", + "@signorecello/noir_playground": "^0.6.0", "axios": "^1.4.0", "clsx": "^1.2.1", - "docusaurus-plugin-typedoc": "1.0.0-next.18", "hast-util-is-element": "^1.1.0", - "prism-react-renderer": "^1.3.5", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "rehype-katex": "^5.0.0", - "remark-math": "^3.0.1", + "prism-react-renderer": "^2.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-spinners": "^0.13.8", + "rehype-katex": "^7.0.0", + "remark-math": "^6.0.0" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "^3.0.1", + "@docusaurus/tsconfig": "^3.0.1", + "@docusaurus/types": "^3.0.1", + "@types/prettier": "^3", + "docusaurus-plugin-typedoc": "1.0.0-next.18", + "eslint-plugin-prettier": "^5.0.0", + "prettier": "3.0.3", + "serve": "^14.2.1", + "ts-node": "^10.9.1", "typedoc": "^0.25.0", "typedoc-plugin-frontmatter": "^0.0.2", "typedoc-plugin-markdown": "4.0.0-next.25", "typedoc-plugin-merge-modules": "^5.1.0", - "typescript": "^5.2.2" - }, - "devDependencies": { - "@docusaurus/module-type-aliases": "^2.4.0" + "typescript": "~5.2.2" }, "browserslist": { "production": [ @@ -44,6 +56,6 @@ ] }, "engines": { - "node": ">=16.14" + "node": ">=18-0" } } diff --git a/docs/scripts/setStable.js b/docs/scripts/setStable.js deleted file mode 100644 index 4bbe283f4b..0000000000 --- a/docs/scripts/setStable.js +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable */ -const fs = require('fs'); -const path = require('path'); -const axios = require('axios'); -const { release } = require('os'); - -const IGNORE_VERSIONS = ['0.16.0']; -const NUMBER_OF_VERSIONS_TO_SHOW = 4; - -async function main() { - const versionsFile = path.join(__dirname, '../versions.json'); - - const axiosOpts = { - params: { per_page: 100 }, - }; - - console.log(process.env.GITHUB_TOKEN); - // cool if you have a GITHUB_TOKEN because of rate limiting - // but fine if you don't - if (process.env.GITHUB_TOKEN) axiosOpts.headers = { Authorization: `token ${process.env.GITHUB_TOKEN}` }; - - const { data } = await axios.get('https://api.github.com/repos/noir-lang/noir/releases', axiosOpts); - - const all = data.map((release) => release.tag_name); - console.log('All versions: ', all); - const aztecs = data.filter((release) => release.tag_name.includes('aztec')).map((release) => release.tag_name); - console.log('Removing aztecs: ', aztecs); - const prereleases = data.filter((release) => !release.prerelease).map((release) => release.tag_name); - console.log('Removing prereleases: ', prereleases); - - const stables = data - .filter((release) => !release.prerelease && !release.tag_name.includes('aztec')) - .filter((release) => !IGNORE_VERSIONS.includes(release.tag_name.replace('v', ''))) - .map((release) => release.tag_name) - .slice(0, NUMBER_OF_VERSIONS_TO_SHOW); - - console.log('Stables: ', stables); - - fs.writeFileSync(versionsFile, JSON.stringify(stables, null, 2)); -} - -main(); diff --git a/docs/scripts/setStable.ts b/docs/scripts/setStable.ts new file mode 100644 index 0000000000..e23d990763 --- /dev/null +++ b/docs/scripts/setStable.ts @@ -0,0 +1,38 @@ +const fs = require('fs'); +const path = require('path'); +const axios = require('axios'); + +const IGNORE_VERSIONS = ['0.16.0']; +const NUMBER_OF_VERSIONS_TO_SHOW = 4; + +async function main() { + const versionsFile = path.resolve('../versions.json'); + + const axiosOpts = { + params: { per_page: 100 }, + headers: {}, + }; + + if (process.env.GITHUB_TOKEN) axiosOpts.headers = { Authorization: `token ${process.env.GITHUB_TOKEN}` }; + + const { data } = await axios.get('https://api.github.com/repos/noir-lang/noir/releases', axiosOpts); + + const all = data.map((release) => release.tag_name); + console.log('All versions: ', all); + const aztecs = data.filter((release) => release.tag_name.includes('aztec')).map((release) => release.tag_name); + console.log('Removing aztecs: ', aztecs); + const prereleases = data.filter((release) => !release.prerelease).map((release) => release.tag_name); + console.log('Removing prereleases: ', prereleases); + + const stables = data + .filter((release) => !release.prerelease && !release.tag_name.includes('aztec')) + .filter((release) => !IGNORE_VERSIONS.includes(release.tag_name.replace('v', ''))) + .map((release) => release.tag_name) + .slice(0, NUMBER_OF_VERSIONS_TO_SHOW); + + console.log('Stables: ', stables); + + fs.writeFileSync(versionsFile, JSON.stringify(stables, null, 2)); +} + +main(); diff --git a/docs/sidebars.js b/docs/sidebars.js index 3fd391cf09..016ead14a8 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -1,145 +1,55 @@ -/** - * Creating a sidebar enables you to: - - create an ordered group of docs - - render a sidebar for each doc of that group - - provide next/previous navigation - - The sidebars can be generated from the filesystem, or explicitly defined here. - - Create as many sidebars as you want. - */ - -// @ts-check - /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ -const sidebars = { +export default { sidebar: [ { type: 'doc', id: 'index', - label: 'Noir', }, { type: 'category', label: 'Getting Started', - items: [{ type: 'autogenerated', dirName: 'getting_started' }], - }, - { - type: 'category', - label: 'Examples', - items: [{ type: 'autogenerated', dirName: 'examples' }], - }, - { - type: 'category', - label: 'Nargo', - items: [{ type: 'autogenerated', dirName: 'nargo' }], - }, - { - type: 'category', - label: 'Language Concepts', items: [ { - type: 'category', - label: 'Data Types', - link: { - type: 'doc', - id: 'language_concepts/data_types', - }, - items: [ - { - type: 'autogenerated', - dirName: 'language_concepts/data_types', - }, - ], + type: 'autogenerated', + dirName: 'getting_started', }, - 'language_concepts/functions', - 'language_concepts/control_flow', - 'language_concepts/ops', - 'language_concepts/assert', - 'language_concepts/unconstrained', - 'language_concepts/generics', - 'language_concepts/mutability', - 'language_concepts/lambdas', - 'language_concepts/comments', - 'language_concepts/distinct', - 'language_concepts/shadowing', ], }, { type: 'category', - label: 'Noir Standard Library', + label: 'The Noir Language', items: [ { - type: 'category', - label: 'Cryptographic Primitives', - link: { - type: 'doc', - id: 'standard_library/cryptographic_primitives', - }, - items: [ - { - type: 'autogenerated', - dirName: 'standard_library/cryptographic_primitives', - }, - ], + type: 'autogenerated', + dirName: 'explanations', }, - 'standard_library/recursion', - 'standard_library/logging', - 'standard_library/merkle_trees', - 'standard_library/zeroed', - 'standard_library/black_box_fns', - 'standard_library/options', ], }, { type: 'category', - label: 'Modules, Packages and Crates', - items: [{ type: 'autogenerated', dirName: 'modules_packages_crates' }], + label: 'How To Guides', + items: [ + { + type: 'autogenerated', + dirName: 'how_to', + }, + ], }, { type: 'category', - label: 'NoirJS', - link: { - type: 'doc', - id: 'noir_js/noir_js', - }, + label: 'Tutorials', items: [ { - type: 'category', - label: 'Guides', - items: [ - { - type: 'autogenerated', - dirName: 'noir_js/getting_started', - }, - ], - }, - { - type: 'category', - label: 'Reference', - items: [ - { - type: 'category', - label: 'Noir JS', - link: { - type: 'doc', - id: 'noir_js/reference/noir_js/index', - }, - items: require('./docs/noir_js/reference/noir_js/typedoc-sidebar.cjs'), - }, - { - type: 'category', - label: 'Backend Barretenberg', - link: { - type: 'doc', - id: 'noir_js/reference/backend_barretenberg/index', - }, - items: require('./docs/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs'), - }, - ], + type: 'autogenerated', + dirName: 'tutorials', }, ], }, + { + type: 'category', + label: 'Reference', + items: [{ type: 'autogenerated', dirName: 'reference' }], + }, { type: 'doc', id: 'migration_notes', @@ -147,5 +57,3 @@ const sidebars = { }, ], }; - -module.exports = sidebars; diff --git a/docs/src/components/GithubCode/index.js b/docs/src/components/GithubCode/index.js deleted file mode 100644 index 69ba17ef79..0000000000 --- a/docs/src/components/GithubCode/index.js +++ /dev/null @@ -1,63 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import axios from 'axios'; -import Highlight, { defaultProps } from "prism-react-renderer"; -import github from 'prism-react-renderer/themes/github'; -//import vsDark from 'prism-react-renderer/themes/vsDark'; - -const GitHubCode = ({ owner, repo, branch = 'master', filePath, language, startLine = 1, endLine = Infinity }) => { - const [code, setCode] = useState(''); - const [response, setResponse] = useState(''); - - useEffect(() => { - const fetchCode = async () => { - const url = `https://api.github.com/repos/${owner}/${repo}/contents/${filePath}?ref=${branch}` - try { - const response = await axios.get(url); - const content = response.data.content; - const decodedContent = atob(content); // Decode Base64 content - - const lines = decodedContent.split('\n'); - const desiredLines = lines.slice(startLine - 1, endLine).join('\n').trimEnd(); - - setResponse(response); - setCode(desiredLines); - } catch (error) { - console.error('Failed to fetch GitHub code:', error); - } - }; - - fetchCode(); - }, [owner, repo, branch, filePath, startLine, endLine]); - - const highlightedCode = ( - - {({ className, style, tokens, getLineProps, getTokenProps }) => ( -
-
-                        {tokens.map((line, i) => (
-                            
- {/* uncomment for line numbers */} - {/* {i + 1} */} - {line.map((token, key) => ( - - ))} -
- ))} -
- { - response.data?.html_url ? Link to source code. : '' - } -
- )} -
- ) - - return highlightedCode; -}; - -export default GitHubCode; \ No newline at end of file diff --git a/docs/src/components/HomepageFeatures/index.js b/docs/src/components/HomepageFeatures/index.js deleted file mode 100644 index 78f410ba68..0000000000 --- a/docs/src/components/HomepageFeatures/index.js +++ /dev/null @@ -1,64 +0,0 @@ -import React from 'react'; -import clsx from 'clsx'; -import styles from './styles.module.css'; - -const FeatureList = [ - { - title: 'Easy to Use', - Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default, - description: ( - <> - Docusaurus was designed from the ground up to be easily installed and - used to get your website up and running quickly. - - ), - }, - { - title: 'Focus on What Matters', - Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default, - description: ( - <> - Docusaurus lets you focus on your docs, and we'll do the chores. Go - ahead and move your docs into the docs directory. - - ), - }, - { - title: 'Powered by React', - Svg: require('@site/static/img/undraw_docusaurus_react.svg').default, - description: ( - <> - Extend or customize your website layout by reusing React. Docusaurus can - be extended while reusing the same header and footer. - - ), - }, -]; - -function Feature({Svg, title, description}) { - return ( -
-
- -
-
-

{title}

-

{description}

-
-
- ); -} - -export default function HomepageFeatures() { - return ( -
-
-
- {FeatureList.map((props, idx) => ( - - ))} -
-
-
- ); -} diff --git a/docs/src/components/HomepageFeatures/styles.module.css b/docs/src/components/HomepageFeatures/styles.module.css deleted file mode 100644 index b248eb2e5d..0000000000 --- a/docs/src/components/HomepageFeatures/styles.module.css +++ /dev/null @@ -1,11 +0,0 @@ -.features { - display: flex; - align-items: center; - padding: 2rem 0; - width: 100%; -} - -.featureSvg { - height: 200px; - width: 200px; -} diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index c1faa9d313..53dec74151 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -68,3 +68,58 @@ html[data-theme='dark'] { .katex-html { display: none; } + +.homepage_layout { + max-width: 800px; + margin: 0 auto; +} + +.homepage_h1 { + display: block; + margin: 40px auto; + text-align: center; +} + +.homepage_p { + display: block; + margin: 0 auto; + text-align: center; +} + +.homepage_cta_container { + display: flex; + justify-content: center; + margin: 0 auto; + text-align: center; + background: white; + border: none; + width: 50%; +} + +.homepage_cta { + display: block; + margin: 50px auto; + text-align: center; +} + +.cards__container { + margin: 0 auto; +} + + +.card__body { + display: flex; + flex-wrap: wrap; +} + +.card__body.align_right { + justify-content: end; + text-align: right; +} + +*, +::before, +::after { + border-width: 0; + border-style: solid; +} diff --git a/docs/src/pages/index.jsx b/docs/src/pages/index.jsx new file mode 100644 index 0000000000..8485a73078 --- /dev/null +++ b/docs/src/pages/index.jsx @@ -0,0 +1,71 @@ +import React, { lazy, Suspense } from 'react'; +import Layout from '@theme/Layout'; +import Link from '@docusaurus/Link'; + +import headerPic from '../../static/img/homepage_header_pic.png'; +import { BeatLoader } from 'react-spinners'; + +const NoirEditor = lazy(() => import('@signorecello/noir_playground')); + +const Spinner = () => { + return ( +
+ +
+ ); +}; + +export default function Landing() { + const [tryIt, setTryIt] = React.useState(false); + + return ( + +
+
+
+

+ Noir +

+

+ Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR + compatible proving system. It's design choices are influenced heavily by Rust and focuses on a simple, + familiar syntax. +

+ + {tryIt && ( + }> + + + + + + )} + + {!tryIt && ( +
+ + + + +
+ )} +
+
+ + ); +} diff --git a/docs/static/img/homepage_header_pic.png b/docs/static/img/homepage_header_pic.png new file mode 100644 index 0000000000..d629e20223 Binary files /dev/null and b/docs/static/img/homepage_header_pic.png differ diff --git a/docs/tsconfig.json b/docs/tsconfig.json new file mode 100644 index 0000000000..01b56ec598 --- /dev/null +++ b/docs/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "@docusaurus/tsconfig", + "compilerOptions": { + "baseUrl": "." + }, +} diff --git a/docs/versioned_docs/version-v0.10.5/examples/merkle-proof.mdx b/docs/versioned_docs/version-v0.10.5/examples/merkle-proof.mdx deleted file mode 100644 index 6430780817..0000000000 --- a/docs/versioned_docs/version-v0.10.5/examples/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md deleted file mode 100644 index de30869732..0000000000 --- a/docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,285 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [TypeScript](../typescript). - -### UltraPlonk - -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Install via Nix](#option-3-install-via-nix) -- [Option 4: Compile from Source](#option-4-compile-from-source) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Windows (PowerShell) - -Open PowerShell as Administrator and run: - -```powershell -mkdir -f -p "$env:USERPROFILE\.nargo\bin\"; ` -Invoke-RestMethod -Method Get -Uri https://github.com/noir-lang/noir/releases/download/v0.4.1/nargo-x86_64-pc-windows-msvc.zip -Outfile "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip"; ` -Expand-Archive -Path "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip" -DestinationPath "$env:USERPROFILE\.nargo\bin\"; ` -$Reg = "Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment"; ` -$OldPath = (Get-ItemProperty -Path "$Reg" -Name PATH).Path; ` -$NewPath = $OldPath + ’;’ + "$env:USERPROFILE\.nargo\bin\"; ` -Set-ItemProperty -Path "$Reg" -Name PATH –Value "$NewPath"; ` -$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Install via Nix - -Due to the large number of native dependencies, Noir projects can be installed via [Nix](https://nixos.org/). - -#### Installing Nix - -For the best experience, please follow these instructions to setup Nix: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -#### Install Nargo into your Nix profile - -1. Use `nix profile` to install Nargo - -```sh -nix profile install github:noir-lang/noir -``` - -### Option 4: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `flake.nix`, which is 1.66.0 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git -[rust]: https://www.rust-lang.org/tools/install -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir -[homebrew]: https://brew.sh/ -[cmake]: https://cmake.org/install/ -[llvm]: https://llvm.org/docs/GettingStarted.html -[openmp]: https://openmp.llvm.org/ -[barretenberg]: https://github.com/AztecProtocol/barretenberg diff --git a/docs/versioned_docs/version-v0.10.5/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.10.5/getting_started/02_breakdown.md deleted file mode 100644 index 3fa3a35766..0000000000 --- a/docs/versioned_docs/version-v0.10.5/getting_started/02_breakdown.md +++ /dev/null @@ -1,200 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -### Prover.toml - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -### Verifier.toml - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -### Nargo.toml - -_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. - -Example Nargo.toml: - -```toml -[package] -name = "noirstarter" -type = "bin" -authors = ["Alice"] -compiler_version = "0.9.0" -description = "Getting started with Noir" -entry = "circuit/main.nr" -license = "MIT" - -[dependencies] -ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} -``` - -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -#### Package section - -The package section requires a number of fields including: - -- `name` (**required**) - the name of the package -- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract -- `authors` (optional) - authors of the project -- `compiler_version` (optional) - specifies the version of the compiler to use. This is not currently enforced by the compiler, but will be in future versions. -- `description` (optional) -- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) -- `backend` (optional) -- `license` (optional) - -#### Dependencies section - -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. - -`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: - -```bash -nargo prove -p OtherProver -``` - -## Verifying a Proof - -When the command `nargo verify` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. - -In the [next section](language_server), we will explain how to utilize the Noir Language Server. diff --git a/docs/versioned_docs/version-v0.10.5/getting_started/03_language_server.md b/docs/versioned_docs/version-v0.10.5/getting_started/03_language_server.md deleted file mode 100644 index 49bd1d2467..0000000000 --- a/docs/versioned_docs/version-v0.10.5/getting_started/03_language_server.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: Language Server -description: - Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: - [Nargo, Language Server, LSP, VSCode, Visual Studio Code] ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -When you language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, execution, and tests: - -![Compile and Execute](@site/static/img/codelens_compile_execute.png) -![Run test](@site/static/img/codelens_run_test.png) - -### Configuration - -* __Noir: Enable LSP__ - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -* __Noir: Nargo Flags__ - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -* __Noir: Nargo Path__ - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -* __Noir > Trace: Server__ - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.10.5/index.md b/docs/versioned_docs/version-v0.10.5/index.md deleted file mode 100644 index e56b24bccd..0000000000 --- a/docs/versioned_docs/version-v0.10.5/index.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -This version of the book is being released with the public alpha. There will be a lot of features -that are missing in this version, however the syntax and the feel of the language will mostly be -completed. - -## What is Noir? - -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. - -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Solidity Developers - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen -- HashToField - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.10.5/language_concepts/01_functions.md deleted file mode 100644 index 7cb43c4c5f..0000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/01_functions.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : pub Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : pub Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` - -## Lambdas - -Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. - -```rust -let add_50 = |val| val + 50; -assert(add_50(100) == 150); -``` - -See [Lambdas](./08_lambdas.md) for more details. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.10.5/language_concepts/02_control_flow.md deleted file mode 100644 index 691c514d9a..0000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/02_control_flow.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md deleted file mode 100644 index da02b12605..0000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.10.5/language_concepts/04_assert.md deleted file mode 100644 index a25a946123..0000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/04_assert.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. - -### Example - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -The above snippet compiles because `==` is a predicate operation. Conversely, the following will not -compile: - -```rust -// INCORRECT - -fn main(x : Field, y : Field) { - assert(x + y); -} -``` - -> The rationale behind this not compiling is due to ambiguity. It is not clear if the above should -> equate to `x + y == 0` or if it should check the truthiness of the result. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.10.5/language_concepts/07_mutability.md deleted file mode 100644 index 4641521b1d..0000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/07_mutability.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a }; -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -:::warning - -The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. - -::: - -## Globals - -Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * mysubmodule::N; - assert(res != res2); -} - -mod mysubmodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md deleted file mode 100644 index 658a0441ff..0000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: Fields -description: - Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. -keywords: - [ - noir, - field type, - methods, - examples, - best practices, - ] ---- - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -## Methods - -After declaring a Field, you can use these common methods on it: - -### to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_le_bits(32); -} -``` - -### to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2; - let bits = field.to_be_bits(32); -} -``` - -### to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_le_bytes(4); -} -``` - -### to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let bytes = field.to_be_bytes(4); -} -``` - -### to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_le_radix(256, 4); -} -``` - -### to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2; - let radix = field.to_be_radix(256, 4); -} -``` - -### pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -### sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/01_integers.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/01_integers.md deleted file mode 100644 index d9c5e20e79..0000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/01_integers.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Integers -description: - Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. -keywords: - [ - noir, - integer types, - methods, - examples, - arithmetic, - ] ---- - -An integer type is a range constrained field type. The Noir frontend currently supports unsigned, -arbitrary-sized integer types. - -An integer type is specified first with the letter `u`, indicating its unsigned nature, followed by -its length in bits (e.g. `32`). For example, a `u32` variable can store a value in the range of -$\\([0,2^{32}-1]\\)$: - -```rust -fn main(x : Field, y : u32) { - let z = x as u32 + y; -} -``` - -`x`, `y` and `z` are all private values in this example. However, `x` is a field while `y` and `z` -are unsigned 32-bit integers. If `y` or `z` exceeds the range $\\([0,2^{32}-1]\\)$, proofs created -will be rejected by the verifier. - -> **Note:** The default backend supports both even (e.g. `u16`, `u48`) and odd (e.g. `u5`, `u3`) -> sized integer types. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/03_strings.md deleted file mode 100644 index ee69853bfb..0000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/03_strings.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Strings -description: - Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. -keywords: - [ - noir, - string type, - methods, - examples, - concatenation, - ] ---- - - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). - -```rust -use dep::std; - -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -You can convert a `str` to a byte array by calling `as_bytes()` -or a vector by calling `as_bytes_vec()`. - -```rust -fn main() { - let message = "hello world"; - let message_bytes = message.as_bytes(); - let mut message_vec = message.as_bytes_vec(); - assert(message_bytes.len() == 11); - assert(message_bytes[0] == 104); - assert(message_bytes[0] == message_vec.get(0)); -} -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/04_arrays.md deleted file mode 100644 index f826b39bf3..0000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/04_arrays.md +++ /dev/null @@ -1,237 +0,0 @@ ---- -title: Arrays -description: - Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. -keywords: - [ - noir, - array type, - methods, - examples, - indexing, - ] ---- - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: - -```rust -let array: [Field; 32] = [0; 32]; -let sl = array.as_slice() -``` - -## Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for arrays: - -### len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -### sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -### sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a < b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a > b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -### map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -### fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -### reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -### all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -### any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/05_slices.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/05_slices.md deleted file mode 100644 index bc7f5c531e..0000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/05_slices.md +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: Slices -description: - Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. -keywords: - [ - noir, - slice type, - methods, - examples, - subarrays, - ] ---- - -:::caution - -This feature is experimental. You should expect it to change in future versions, -cause unexpected behavior, or simply not work at all. - -::: - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here]([test-file]. - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - -## Methods - -For convenience, the STD provides some ready-to-use, common methods for slices: - -### push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -### push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -### pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -### pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -### append - -Loops over a slice and adds it to the end of another. - -```rust -fn append(mut self, other: Self) -> Self -``` - -Example: - -```rust -let append = [1, 2].append([3, 4, 5]); -``` - -### insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust -new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -### remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/06_vectors.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/06_vectors.md deleted file mode 100644 index c5b74c877f..0000000000 --- a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/06_vectors.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Vectors -description: - Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. -keywords: - [ - noir, - vector type, - methods, - examples, - dynamic arrays, - ] ---- - -:::caution - -This feature is experimental. You should expect it to change in future versions, -cause unexpected behavior, or simply not work at all. - -::: - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -use dep::std::collections::vec::Vec; - -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` diff --git a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.10.5/modules_packages_crates/dependencies.md deleted file mode 100644 index 9e6463801b..0000000000 --- a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: - -```toml -# Nargo.toml - -[dependencies] -easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/src/contracts/easy_private_token_contract"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -```tree -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── liba - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -libA = { path = "../liba" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: - -```rust -use dep::ecrecover; -use dep::libA; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.10.5/modules_packages_crates/workspaces.md deleted file mode 100644 index eaa0950669..0000000000 --- a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/workspaces.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Workspaces ---- - -Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. - -Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. - -For a project with the following structure: - -```tree -├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml -``` - -You can define a workspace in Nargo.toml like so: - -```toml -[workspace] -members = ["crates/a", "crates/b"] -default-member = "crates/a" -``` - -`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. - -`default-member` indicates which package various commands process by default. - -Libraries can be defined in a workspace. We just don't have a way to consume libraries from inside a workspace as external dependencies right now. - -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/versioned_docs/version-v0.10.5/nargo/01_commands.md b/docs/versioned_docs/version-v0.10.5/nargo/01_commands.md deleted file mode 100644 index 425a73a34c..0000000000 --- a/docs/versioned_docs/version-v0.10.5/nargo/01_commands.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -``` -Options: - --show-ssa Emit debug information for the intermediate SSA IR - --deny-warnings Quit execution when warnings are emitted - -h, --help Print help -``` - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -- `` - The subcommand whose help message to display - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -**Options** - -``` - --package The name of the package to check - --workspace Check all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -## `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -**Options** - -``` - --package The name of the package to codegen - --workspace Codegen all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -## `nargo compile` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -You can also use "build" as an alias for compile (e.g. `nargo build`). - -**Options** - -``` - --include-keys Include Proving and Verification keys in the build artifacts - --package The name of the package to compile - --workspace Compile all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -## `nargo new ` - -Creates a new Noir project in a new folder. - -**Arguments** - -``` - The path to save the new project -``` - -**Options** - -``` - --name Name of the package [default: package directory name] - --lib Use a library template - --bin Use a binary template [default] - --contract Use a contract template --h, --help Print help -``` - -## `nargo init` - -Creates a new Noir project in the current directory. - -**Options** - -``` - --name Name of the package [default: current directory name] - --lib Use a library template - --bin Use a binary template [default] - --contract Use a contract template --h, --help Print help -``` - -## `nargo execute [WITNESS_NAME]` - -Runs the Noir program and prints its return value. - -**Arguments** - -``` -[WITNESS_NAME] Write the execution witness to named file -``` - -**Options** - -``` --p, --prover-name The name of the toml file which contains the inputs for the prover [default: Prover] - --package The name of the package to execute - --workspace Execute all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A -`.tr` file will then be saved in the `./target` folder. - -> **Info:** The `.tr` file is the witness file. The witness file can be considered as program inputs -> parsed for your program's ACIR. -> -> This file can be passed along with circuit's ACIR into a TypeScript project for proving and -> verification. See the [TypeScript](../typescript#proving-and-verifying-externally-compiled-files) -> section to learn more. - -## `nargo prove` - -Creates a proof for the program. - -**Options** - -``` --p, --prover-name The name of the toml file which contains the inputs for the prover [default: Prover] --v, --verifier-name The name of the toml file which contains the inputs for the verifier [default: Verifier] - --verify Verify proof after proving - --package The name of the package to prove - --workspace Prove all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -## `nargo verify` - -Given a proof and a program, verify whether the proof is valid. - -**Options** - -``` --v, --verifier-name The name of the toml file which contains the inputs for the verifier [default: Verifier] - --package The name of the package verify - --workspace Verify all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -## `nargo test [TEST_NAME]` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. - -Takes an optional `--exact` flag which allows you to select tests based on an exact name. - -See an example on the [testing page](./testing). - -**Options** - -``` - --show-output Display output of `println` statements - --exact Only run tests that match exactly - --package The name of the package to test - --workspace Test all packages in the workspace - --print-acir Display the ACIR for compiled circuit - --deny-warnings Treat all warnings as errors --h, --help Print help -``` - -## `nargo info` - -Prints a table containing the information of the package. - -Currently the table provide - -1. The number of ACIR opcodes -2. The final number gates in the circuit used by a backend - -If the file contains a contract the table will provide the -above information about each function of the contract. - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). diff --git a/docs/versioned_docs/version-v0.10.5/nargo/02_testing.md b/docs/versioned_docs/version-v0.10.5/nargo/02_testing.md deleted file mode 100644 index 106952c44c..0000000000 --- a/docs/versioned_docs/version-v0.10.5/nargo/02_testing.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -### Test fail - -You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test(should_fail)] -fn test_add() { - assert(add(2,2) == 5); -} -``` diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.10.5/standard_library/black_box_fns.md deleted file mode 100644 index c758846b68..0000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/black_box_fns.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen](./cryptographic_primitives/hashes#pedersen) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index 1d9b1c7f09..0000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::pedersen(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index 62265cddb1..0000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: - See how you can perform scalar multiplications over a fixed base in Noir -keywords: - [ - cryptographic primitives, - Noir project, - scalar multiplication, - ] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## scalar_mul::fixed_base - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base(x); - std::println(scal); -} -``` - - diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index 0e219c0e5f..0000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx deleted file mode 100644 index 3934a0338d..0000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/05_eddsa.mdx deleted file mode 100644 index 8f060ed331..0000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/05_eddsa.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/common/_blackbox.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/common/_blackbox.mdx deleted file mode 100644 index 9fe9b48fbf..0000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/common/_blackbox.mdx +++ /dev/null @@ -1,5 +0,0 @@ -:::info - -This is a black box function. Read [this section](../black_box_fns) to learn more about black box functions in Noir. - -::: \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.10.5/standard_library/merkle_trees.md deleted file mode 100644 index 57d8c4a9e4..0000000000 --- a/docs/versioned_docs/version-v0.10.5/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/docs/versioned_docs/version-v0.10.5/typescript.md b/docs/versioned_docs/version-v0.10.5/typescript.md deleted file mode 100644 index 258a2160e9..0000000000 --- a/docs/versioned_docs/version-v0.10.5/typescript.md +++ /dev/null @@ -1,237 +0,0 @@ ---- -title: Working with TypeScript -description: - Learn how to interact with Noir programs using TypeScript. Follow this tutorial to compile your - program, specify inputs, initialize a prover & verifier, and prove and verify your program. -keywords: [TypeScript, Noir, tutorial, compile, inputs, prover, verifier, proof] ---- - -Interactions with Noir programs can also be performed in TypeScript, which can come in handy when -writing tests or when working in TypeScript-based projects like [Hardhat](https://hardhat.org/). - -You can check the complete code for this tutorial here: [browser with next.js](https://github.com/signorecello/noir-min-browser-example) and [node.js](https://github.com/signorecello/noir-min-nodejs-example). If you want just a browser boilerplate to start with, check out the [noir-starter](https://github.com/noir-lang/noir-starter) for an example implementation. - -:::note - -You may find unexpected errors working with some frameworks such as `vite`. This is due to the -nature of `wasm` files and the way Noir uses web workers. As we figure it out, we suggest using -[Create React App](https://create-react-app.dev/), or [Next.js](https://nextjs.org/) for a quick -start. - -::: - -## Setup - -Make sure you are using Noir version >= 0.10.1. - -You can check your current version by running `nargo --version`. - -See the [Installation page](./getting_started/nargo_installation) for more info. - -We're assuming you're using ES6 and ESM for both browser (for example with React), or nodejs. Install [Node.js](https://nodejs.org/en). Init a new project with `npm init` and add `"type": "module"` to your `package.json`, to let `node` know we're using the new ESM sytem: - -```json -{ - "type": "module" - // the rest of your package.json -} -``` - -Install Noir dependencies in your project by running: - -```bash -npm i @aztec/bb.js@0.3.6 https://git@github.com/noir-lang/acvm-simulator-wasm.git#b9d9ca9dfc5140839f23998d9466307215607c42 fflate ethers@5.7.2 -``` - -This will install the `acvm-simulator` that will generate our witness, and the proving backend barretenberg `bb.js`. - -We're also installing `ethers` because we're too lazy to write a function that pads public inputs with 32bytes, and `fflate` to help us decompress our circuit bytecode. - -Since we're with typescript and using `nodejs` types, we also recommend to install the `@types/node` package, otherwise your IDE will scream at you. - -```bash -npm i --save-dev @types/node -``` - -:::note - -While Noir is in rapid development, some packages could interfere with others. For that reason, you -should use these specified versions. Let us know if for some reason you need to use other ones. - -::: - -As for the circuit, run `nargo init` to create a new Noir project. - -We will use a Standard Noir Example and place it in the `src` folder. This program simply multiplies input `x` with input `y` and returns the result `z`. The verifier doesn't know the value of `x`: we're proving that we know it without making it public. - -```rust -// src/main.nr -fn main(x: u32, y: pub u32) -> pub u32 { - let z = x * y; - z -} -``` - -One valid scenario for proving could be `x = 3`, `y = 4` and `return = 12` - -## Compiling - -In order to start proving, we need to compile our circuit into the intermediate representation used by our backend. As of today, you have to do that with `nargo`. Just hop to your circuits folder and run `nargo compile`. - -:::info - -At this time, you need to use a nightly version of nargo. Using [noirup](./getting_started/00_nargo_installation.md#option-1-noirup) you can do this simply by running `noirup -n`. - -::: - -You should have a `json` file in `target/` with your circuit's bytecode. The json file is name based on the project name specified in Nargo.toml, so for a project named "test", it will be at `target/test.json`. You can then import that file normally. - -```ts -import circuit from '../target/test.json' assert { type: 'json' }; -``` - -## Decompressing the circuit - -The compiled circuit comes compressed. We need to decompress it, that's where `fflate` comes in. - -```ts -import { decompressSync } from 'fflate'; - -const acirBuffer = Buffer.from(circuit.bytecode, 'base64'); -const acirBufferUncompressed = decompressSync(acirBuffer); -``` - -From here, it's highly recommended you store `acirBuffer` and `acirBufferUncompressed` close by, as they will be used for witness generation and proving. - -## Initializing ACVM and BB.JS - -:::note - -This step will eventually be abstracted away as Noir tooling matures. For now, you should be fine just literally copy-pasting most of this into your own code. - -::: - -Before proving, `bb.js` needs to be initialized. We need to import some functions and use them - -```ts -import { Crs, newBarretenbergApiAsync, RawBuffer } from '@aztec/bb.js/dest/node/index.js'; - -const api = await newBarretenbergApiAsync(4); - -const [exact, circuitSize, subgroup] = await api.acirGetCircuitSizes(acirBufferUncompressed); -const subgroupSize = Math.pow(2, Math.ceil(Math.log2(circuitSize))); -const crs = await Crs.new(subgroupSize + 1); -await api.commonInitSlabAllocator(subgroupSize); -await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data())); - -const acirComposer = await api.acirNewAcirComposer(subgroupSize); -``` - -We should take two very useful objects from here: `api` and `acirComposer`. Make sure to keep these close by! - -:::info - -On the browser, you also need to init the ACVM. You can do that by importing it and calling it like: - -```ts -import initACVM, { executeCircuit, compressWitness } from '@noir-lang/acvm_js'; - -await initACVM(); -// the rest of your code -``` - -::: - -## Generating witnesses - -Witness generation is what allows us to prove with arbitrary inputs (like user inputs on a form, game, etc). In this example, our input is a simple object with our circuit inputs `x`, `y`, and return `z` (fun fact: the return value in Noir is actually a public input!). We're wrapping it in a function, so it can be conveniently called later on. - -```ts -import { ethers } from 'ethers'; // I'm lazy so I'm using ethers to pad my input -import { executeCircuit, compressWitness } from '@noir-lang/acvm_js'; - -async function generateWitness(input: any, acirBuffer: Buffer): Promise { - const initialWitness = new Map(); - initialWitness.set(1, ethers.utils.hexZeroPad(`0x${input.x.toString(16)}`, 32)); - initialWitness.set(2, ethers.utils.hexZeroPad(`0x${input.y.toString(16)}`, 32)); - - const witnessMap = await executeCircuit(acirBuffer, initialWitness, () => { - throw Error('unexpected oracle'); - }); - - const witnessBuff = compressWitness(witnessMap); - return witnessBuff; -} -``` - -## Proving - -Finally, we're ready to prove with our backend. Just like with the witness generation, could be useful to wrap it in its own function: - -```ts -async function generateProof(witness: Uint8Array) { - const proof = await api.acirCreateProof( - acirComposer, - acirBufferUncompressed, - decompressSync(witness), - false, - ); - return proof; -} -``` - -## Verifying - -Our backend should also be ready to verify our proof: - -```ts -async function verifyProof(proof: Uint8Array) { - await api.acirInitProvingKey(acirComposer, acirBufferUncompressed); - const verified = await api.acirVerifyProof(acirComposer, proof, false); - return verified; -} -``` - -## Now for the fun part - -Let's call our functions, and destroy our API! - -```ts -const input = { x: 3, y: 4 }; -const witness = await generateWitness(input, acirBuffer); -console.log('Witness generated!'); -const proof = await generateProof(witness); -console.log('Proof generated!'); -await verifyProof(proof); -console.log('Proof verified!'); -api.destroy(); -``` - -You can use [this](https://gist.github.com/critesjosh/6f3ba19fdc9298b24e90ba4f736247dc) tsconfig.json. You can see the script [here](https://gist.github.com/critesjosh/4aa36e87a0cc3f09feaf1febb4d11348). - -## Verifying with Smart Contract - -Alternatively, a verifier smart contract can be generated and used for verifying Noir proofs in -TypeScript as well. - -This could be useful if the Noir program is designed to be decentrally verified and/or make use of -decentralized states and logics that is handled at the smart contract level. - -This assumes you've already ran `nargo codegen-verifier`, got your smart contract, and deployed it with Hardhat, Foundry, or your tool of choice. You can then verify a Noir proof by simply calling it. - -Currently, `bb.js` appends the public inputs to the proof. However, these inputs need to be fed separately to the verifier contract. A simple solution is to just slice them from the resulting proof, like this: - -```ts -import { ethers } from 'ethers'; // example using ethers v5 -import artifacts from '../artifacts/circuits/contract/plonk_vk.sol/UltraVerifier.json'; // I compiled using Hardhat, so I'm getting my abi from here - -const verifierAddress = '0x123455'; // your verifier address -const provider = new ethers.providers.Web3Provider(window.ethereum); -const signer = this.provider.getSigner(); - -const contract = new ethers.Contract(verifierAddress, artifacts.abi, signer); - -const publicInputs = proof.slice(0, 32); -const slicedProof = proof.slice(32); -await contract.verify(slicedProof, [publicInputs]); -``` diff --git a/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md index 4ff5fc4633..f4ca361d3c 100644 --- a/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.17.0/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noi ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation diff --git a/docs/versioned_docs/version-v0.17.0/index.md b/docs/versioned_docs/version-v0.17.0/index.md index 9ebe1d5494..ddbee58f6e 100644 --- a/docs/versioned_docs/version-v0.17.0/index.md +++ b/docs/versioned_docs/version-v0.17.0/index.md @@ -67,7 +67,7 @@ Compiler: - For expressions - Arrays - Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] - Unsigned integers - If statements - Structures and Tuples diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.17.0/language_concepts/01_functions.md index 47cdea0cf0..5eb22170e5 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/01_functions.md +++ b/docs/versioned_docs/version-v0.17.0/language_concepts/01_functions.md @@ -30,7 +30,7 @@ All parameters in a function must have a type and all types are known at compile is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. ```rust -fn foo(x : Field, y : pub Field){} +fn foo(x : Field, y : Field){} ``` The return type of a function can be stated by using the `->` arrow notation. The function below @@ -38,7 +38,7 @@ states that the foo function must return a `Field`. If the function returns no v is omitted. ```rust -fn foo(x : Field, y : pub Field) -> Field { +fn foo(x : Field, y : Field) -> Field { x + y } ``` diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md index da02b12605..d5caa46376 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.17.0/language_concepts/07_mutability.md index 4641521b1d..ad902c42c9 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/07_mutability.md +++ b/docs/versioned_docs/version-v0.17.0/language_concepts/07_mutability.md @@ -37,7 +37,7 @@ Note that mutability in noir is local and everything is passed by value, so if a mutates its parameters then the parent function will keep the old value of the parameters. ```rust -fn main() -> Field { +fn main() -> pub Field { let x = 3; helper(x); x // x is still 3 diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md index 658a0441ff..78d3d2af16 100644 --- a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md +++ b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md @@ -158,7 +158,7 @@ fn main() { ### sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versioned_docs/version-v0.17.0/migration_notes.md b/docs/versioned_docs/version-v0.17.0/migration_notes.md index 48a8abcf22..69782cba38 100644 --- a/docs/versioned_docs/version-v0.17.0/migration_notes.md +++ b/docs/versioned_docs/version-v0.17.0/migration_notes.md @@ -70,7 +70,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running this bash script: , where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md b/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md index d9e5a0c611..11fef2bf8b 100644 --- a/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md +++ b/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md @@ -74,8 +74,8 @@ async execute(inputs) | Return value | Type | Description | | ------------ | --------------------- | --------------------------------------------------- | -| `witness` | Promise | The witness | -| `returnValue` | Promise | The return value | +| `witness` | Promise \ | The witness | +| `returnValue` | Promise \ | The return value | ### Usage @@ -103,7 +103,7 @@ async generateFinalproof(input) | Return value | Type | Description | | ------------ | --------------------- | --------------------------------------------------- | -| `proof` | Promise | An array with the byte representation of the proof. | +| `proof` | Promise \ | An array with the byte representation of the proof. | ### Usage @@ -133,7 +133,7 @@ async verifyFinalProof(proof) | Return value | Type | Description | | ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise | A boolean for whether the proof was verified | +| `verified` | Promise \ | A boolean for whether the proof was verified | ### Usage diff --git a/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md b/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md index 21c2ff32b5..f444eab177 100644 --- a/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md +++ b/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md @@ -70,7 +70,7 @@ async generateFinalProof(decompressedWitness) | Return value | Type | Description | | ------------ | -------------------- | --------------------------------------------------------- | -| `proof` | Promise | An array with the byte representation of the final proof. | +| `proof` | Promise\ | An array with the byte representation of the final proof. | ### Usage @@ -98,7 +98,7 @@ async generateIntermediateProof(witness) | Return value | Type | Description | | ------------ | -------------------- | --------------------------------------------------------------- | -| `proof` | Promise | An array with the byte representation of the intermediate proof | +| `proof` | Promise\ | An array with the byte representation of the intermediate proof | ### Usage @@ -127,7 +127,7 @@ async generateProof(decompressedWitness, makeEasyToVerifyInCircuit) | Return value | Type | Description | | ------------ | -------------------- | -------------------------------------------------- | -| `proof` | Promise | An array with the byte representation of the proof | +| `proof` | Promise\ | An array with the byte representation of the proof | ### Usage @@ -186,7 +186,7 @@ async verifyFinalProof(proof) | Return value | Type | Description | | ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise | A boolean for whether the proof was verified | +| `verified` | Promise \ | A boolean for whether the proof was verified | ### Usage @@ -214,7 +214,7 @@ async verifyIntermediateProof(proof) | Return value | Type | Description | | ------------ | ------------------ | -------------------------------------------- | -| `verified` | Promise | A boolean for whether the proof was verified | +| `verified` | Promise \ | A boolean for whether the proof was verified | ### Usage diff --git a/docs/docs/examples/merkle-proof.mdx b/docs/versioned_docs/version-v0.19.0/examples/merkle-proof.mdx similarity index 100% rename from docs/docs/examples/merkle-proof.mdx rename to docs/versioned_docs/version-v0.19.0/examples/merkle-proof.mdx diff --git a/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md new file mode 100644 index 0000000000..349756d60c --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/getting_started/00_nargo_installation.md @@ -0,0 +1,249 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, + verifying and more). Learn how to install and use Nargo for your projects with this comprehensive + guide. +keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] +--- + +`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, +verifying and more). + +Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noir_js.md). + +### UltraPlonk + +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. + +## Installation + +There are four approaches for installing Nargo: + +- [Option 1: Noirup](#option-1-noirup) +- [Option 2: Binaries](#option-2-binaries) +- [Option 3: Compile from Source](#option-3-compile-from-source) +- [Option 4: WSL for Windows](#option-4-wsl-for-windows) + +Optionally you can also install [Noir VS Code extension] for syntax highlighting. + +### Option 1: Noirup + +If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a +terminal and run: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done, you should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. + +#### GitHub Actions + +You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as +installing `noirup` and running tests in your GitHub Action `yml` file. + +See the +[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in +this repo containing hash functions in Noir for an example. + +#### Nightly versions + +To install the nightly version of Noir (updated daily) run: + +```bash +noirup -n +``` + +### Option 2: Binaries + +See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous +platform specific binaries. + +#### Step 1 + +Paste and run the following in the terminal to extract and install the binary: + +> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend +> `sudo` and re-run it. + +##### macOS (Apple Silicon) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ +echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ +source ~/.zshrc +``` + +##### macOS (Intel) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ +echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ +source ~/.zshrc +``` + +##### Linux (Bash) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ +echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ +source ~/.bashrc +``` + +#### Step 2 + +Check if the installation was successful by running `nargo --help`. + +> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from +> Finder. Close the new terminal popped up and `nargo` should now be accessible. + +For a successful installation, you should see something similar to the following after running the +command: + +```sh +$ nargo --help + +Noir's package manager + +Usage: nargo + +Commands: + check Checks the constraint system for errors + codegen-verifier Generates a Solidity verifier smart contract for the program + compile Compile the program and its secret execution trace into ACIR format + new Create a new binary project + execute Executes a circuit to calculate its return value + prove Create proof for this program. The proof is returned as a hex encoded string + verify Given a proof and a program, verify whether the proof is valid + test Run the tests for this program + gates Counts the occurrences of different gates in circuit + help Print this message or the help of the given subcommand(s) +``` + +### Option 3: Compile from Source + +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). + +Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. + +#### Setting up your environment + +For the best experience, please follow these instructions to setup your environment: + +1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. +2. Create the file `~/.config/nix/nix.conf` with the contents: + +```ini +experimental-features = nix-command +extra-experimental-features = flakes +``` + +3. Install direnv into your Nix profile by running: + +```sh +nix profile install nixpkgs#direnv +``` + +4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). + 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. +5. Restart your shell. + +#### Shell & editor experience + +Now that your environment is set up, you can get to work on the project. + +1. Clone the repository, such as: + +```sh +git clone git@github.com:noir-lang/noir +``` + +> Replacing `noir` with whichever repository you want to work on. + +2. Navigate to the directory: + +```sh +cd noir +``` + +> Replacing `noir` with whichever repository you cloned. + +3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: + +```sh +direnv allow +``` + +4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. + +5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): + +```sh +code . +``` + +6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. + +#### Building and testing + +Assuming you are using `direnv` to populate your environment, building and testing the project can be done +with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. + +If you want to build the entire project in an isolated sandbox, you can use Nix commands: + +1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. +2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. + +#### Without `direnv` + +If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. + +Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! + +### Option 4: WSL (for Windows) + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). + +Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. + +step 2: Follow the [Noirup instructions](#option-1-noirup). + +## Uninstalling Nargo + +### Noirup + +If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` + +### Nix + +If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. + +```bash +rm ~/.nix-profile/bin/nargo +``` + +[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/docs/docs/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md similarity index 100% rename from docs/docs/getting_started/01_hello_world.md rename to docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md diff --git a/docs/docs/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md similarity index 100% rename from docs/docs/getting_started/02_breakdown.md rename to docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md diff --git a/docs/versioned_docs/version-v0.19.0/index.md b/docs/versioned_docs/version-v0.19.0/index.md new file mode 100644 index 0000000000..4e2f404389 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/index.md @@ -0,0 +1,100 @@ +--- +title: Introducing Noir +description: + Learn about the public alpha release of Noir, a domain specific language heavily influenced by + Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a + rank-1 constraint system. +keywords: + [ + Noir, + Domain Specific Language, + Rust, + Intermediate Language, + Arithmetic Circuit, + Rank-1 Constraint System, + Ethereum Developers, + Protocol Developers, + Blockchain Developers, + Proving System, + Smart Contract Language, + ] +slug: / +--- + +## What is Noir? + +Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. + +It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. + +## Who is Noir for? + +Noir can be used for a variety of purposes. + +### Solidity Developers + +Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will +be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +a verifier contract. + +### Protocol Developers + +As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for +your stack, or maybe you simply want to use a different proving system. Since Noir does not compile +to a specific proof system, it is possible for protocol developers to replace the PLONK-based +proving system with a different proving system altogether. + +### Blockchain developers + +As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the +proving system and smart contract language has been pre-defined). In order for you to use Noir in +your blockchain, a proving system backend and a smart contract interface +must be implemented for it. + +## What's new about Noir? + +Noir is simple and flexible in its design, as it does not compile immediately to a fixed +NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled +to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). + +This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. + +## Current Features + +Compiler: + +- Module System +- For expressions +- Arrays +- Bit Operations +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Unsigned integers +- If statements +- Structures and Tuples +- Generics + +ACIR Supported OPCODES: + +- Sha256 +- Blake2s +- Schnorr signature verification +- MerkleMembership +- Pedersen Commitment +- Pedersen Hash +- HashToField + +## Libraries + +Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). + +Some libraries that are available today include: + +- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library +- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) +- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers +- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address +- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees +- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir +- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers + +See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.19.0/language_concepts/01_functions.md new file mode 100644 index 0000000000..5eb22170e5 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/language_concepts/01_functions.md @@ -0,0 +1,225 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](../nargo/02_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main([1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./06_generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./08_lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](../noir_js/noir_js.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../nargo/02_testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/docs/docs/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.19.0/language_concepts/02_control_flow.md similarity index 100% rename from docs/docs/language_concepts/02_control_flow.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/02_control_flow.md diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md new file mode 100644 index 0000000000..d5caa46376 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/language_concepts/03_ops.md @@ -0,0 +1,97 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | +| >> | Right shift an integer by another integer amount | Types must be integer | +| ! | Bitwise not of a value | Type must be integer or boolean | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | +| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | +| == | returns a bool if one value is equal to the other | Both types must not be constants | +| != | returns a bool if one value is not equal to the other | Both types must not be constants | + +### Predicate Operators + +`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. +This differs from the operations such as `+` where the operands are used in _computation_. + +### Bitwise Operations Example + +```rust +fn main(x : Field) { + let y = x as u32; + let z = y & y; +} +``` + +`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise +`&`. + +> `x & x` would not compile as `x` is a `Field` and not an integer type. + +### Logical Operators + +Noir has no support for the logical operators `||` and `&&`. This is because encoding the +short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can +use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +short-circuiting. + +```rust +let my_val = 5; + +let mut flag = 1; +if (my_val > 6) | (my_val == 0) { + flag = 0; +} +assert(flag == 1); + +if (my_val != 10) & (my_val < 50) { + flag = 0; +} +assert(flag == 0); +``` + +### Shorthand operators + +Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: + +```rust +let mut i = 0; +i = i + 1; +``` + +could be written as: + +```rust +let mut i = 0; +i += 1; +``` diff --git a/docs/docs/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.19.0/language_concepts/04_assert.md similarity index 100% rename from docs/docs/language_concepts/04_assert.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/04_assert.md diff --git a/docs/docs/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.19.0/language_concepts/05_unconstrained.md similarity index 100% rename from docs/docs/language_concepts/05_unconstrained.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/05_unconstrained.md diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.19.0/language_concepts/06_generics.md new file mode 100644 index 0000000000..b700bd5bc5 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/language_concepts/06_generics.md @@ -0,0 +1,113 @@ +--- +title: Generics +description: Learn how to use Generics in Noir +keywords: [Noir, Rust, generics, functions, structs] +--- + +Generics allow you to use the same functions with multiple different concrete data types. You can +read more about the concept of generics in the Rust documentation +[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). + +Here is a trivial example showing the identity function that supports any type. In Rust, it is +common to refer to the most general type as `T`. We follow the same convention in Noir. + +```rust +fn id(x: T) -> T { + x +} +``` + +## In Structs + +Generics are useful for specifying types in structs. For example, we can specify that a field in a +struct will be of a certain generic type. In this case `value` is of type `T`. + +```rust +struct RepeatedValue { + value: T, + count: Field, +} + +impl RepeatedValue { + fn new(value: T) -> Self { + Self { value, count: 1 } + } + + fn increment(mut repeated: Self) -> Self { + repeated.count += 1; + repeated + } + + fn print(self) { + for _i in 0 .. self.count { + dep::std::println(self.value); + } + } +} + +fn main() { + let mut repeated = RepeatedValue::new("Hello!"); + repeated = repeated.increment(); + repeated.print(); +} +``` + +The `print` function will print `Hello!` an arbitrary number of times, twice in this case. + +If we want to be generic over array lengths (which are type-level integers), we can use numeric +generics. Using these looks just like using regular generics, but these generics can resolve to +integers at compile-time, rather than resolving to types. Here's an example of a struct that is +generic over the size of the array it contains internally: + +```rust +struct BigInt { + limbs: [u32; N], +} + +impl BigInt { + // `N` is in scope of all methods in the impl + fn first(first: BigInt, second: BigInt) -> Self { + assert(first.limbs != second.limbs); + first + + fn second(first: BigInt, second: Self) -> Self { + assert(first.limbs != second.limbs); + second + } +} +``` + +## Calling functions on generic parameters + +Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in +Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also +requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? + +The answer is that we can translate this by passing in the function manually. Here's an example of +implementing array equality in Noir: + +```rust +fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { + if array1.len() != array2.len() { + false + } else { + let mut result = true; + for i in 0 .. array1.len() { + result &= elem_eq(array1[i], array2[i]); + } + result + } +} + +fn main() { + assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); + + // We can use array_eq even for arrays of structs, as long as we have + // an equality function for these structs we can pass in + let array = [MyStruct::new(), MyStruct::new()]; + assert(array_eq(array, array, MyStruct::eq)); +} +``` + +You can see an example of generics in the tests +[here](https://github.com/noir-lang/noir/blob/master/crates/nargo_cli/tests/test_data/generics/src/main.nr). diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.19.0/language_concepts/07_mutability.md new file mode 100644 index 0000000000..ad902c42c9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/language_concepts/07_mutability.md @@ -0,0 +1,92 @@ +--- +title: Mutability +description: + Learn about mutable variables, constants, and globals in Noir programming language. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Comptime Values + +:::warning + +The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. + +::: + +## Globals + +Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array +annotations for function parameters and can be imported from submodules. + +```rust +global N: Field = 5; // Same as `global N: Field = 5` + +fn main(x : Field, y : [Field; N]) { + let res = x * N; + + assert(res == y[0]); + + let res2 = x * mysubmodule::N; + assert(res != res2); +} + +mod mysubmodule { + use dep::std; + + global N: Field = 10; + + fn my_helper() -> Field { + let x = N; + x + } +} +``` + +## Why only local mutability? + +Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting +without applying additional overhead to the user. Modeling a mutable reference is not as +straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/docs/language_concepts/08_lambdas.md b/docs/versioned_docs/version-v0.19.0/language_concepts/08_lambdas.md similarity index 100% rename from docs/docs/language_concepts/08_lambdas.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/08_lambdas.md diff --git a/docs/docs/language_concepts/09_comments.md b/docs/versioned_docs/version-v0.19.0/language_concepts/09_comments.md similarity index 100% rename from docs/docs/language_concepts/09_comments.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/09_comments.md diff --git a/docs/docs/language_concepts/10_distinct.md b/docs/versioned_docs/version-v0.19.0/language_concepts/10_distinct.md similarity index 100% rename from docs/docs/language_concepts/10_distinct.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/10_distinct.md diff --git a/docs/docs/language_concepts/11_shadowing.md b/docs/versioned_docs/version-v0.19.0/language_concepts/11_shadowing.md similarity index 100% rename from docs/docs/language_concepts/11_shadowing.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/11_shadowing.md diff --git a/docs/docs/language_concepts/data_types.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types.md similarity index 100% rename from docs/docs/language_concepts/data_types.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/data_types.md diff --git a/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/00_fields.md new file mode 100644 index 0000000000..78d3d2af16 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/00_fields.md @@ -0,0 +1,165 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_le_bits(32); +} +``` + +### to_be_bits + +Transforms the field into an array of bits, Big Endian. + +```rust +fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_be_bits(32); +} +``` + +### to_le_bytes + +Transforms into an array of bytes, Little Endian + +```rust +fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_le_bytes(4); +} +``` + +### to_be_bytes + +Transforms into an array of bytes, Big Endian + +```rust +fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_be_bytes(4); +} +``` + +### to_le_radix + +Decomposes into a vector over the specified base, Little Endian + +```rust +fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_le_radix(256, 4); +} +``` + +### to_be_radix + +Decomposes into a vector over the specified base, Big Endian + +```rust +fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_be_radix(256, 4); +} +``` + +### pow_32 + +Returns the value to the power of the specified exponent + +```rust +fn pow_32(self, exponent: Field) -> Field +``` + +example: + +```rust +fn main() { + let field = 2 + let pow = field.pow_32(4); + assert(pow == 16); +} +``` + +### sgn0 + +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. + +```rust +fn sgn0(self) -> u1 +``` diff --git a/docs/docs/language_concepts/data_types/01_integers.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/01_integers.md similarity index 100% rename from docs/docs/language_concepts/data_types/01_integers.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/data_types/01_integers.md diff --git a/docs/docs/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md similarity index 100% rename from docs/docs/language_concepts/data_types/02_booleans.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md diff --git a/docs/docs/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md similarity index 100% rename from docs/docs/language_concepts/data_types/03_strings.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md diff --git a/docs/docs/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md similarity index 100% rename from docs/docs/language_concepts/data_types/04_arrays.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md diff --git a/docs/docs/language_concepts/data_types/05_slices.mdx b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/05_slices.mdx similarity index 100% rename from docs/docs/language_concepts/data_types/05_slices.mdx rename to docs/versioned_docs/version-v0.19.0/language_concepts/data_types/05_slices.mdx diff --git a/docs/docs/language_concepts/data_types/06_vectors.mdx b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/06_vectors.mdx similarity index 100% rename from docs/docs/language_concepts/data_types/06_vectors.mdx rename to docs/versioned_docs/version-v0.19.0/language_concepts/data_types/06_vectors.mdx diff --git a/docs/docs/language_concepts/data_types/07_tuples.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/07_tuples.md similarity index 100% rename from docs/docs/language_concepts/data_types/07_tuples.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/data_types/07_tuples.md diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/08_structs.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/08_structs.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/language_concepts/data_types/08_structs.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/data_types/08_structs.md diff --git a/docs/docs/language_concepts/data_types/09_references.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/09_references.md similarity index 100% rename from docs/docs/language_concepts/data_types/09_references.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/data_types/09_references.md diff --git a/docs/docs/language_concepts/data_types/10_function_types.md b/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/10_function_types.md similarity index 100% rename from docs/docs/language_concepts/data_types/10_function_types.md rename to docs/versioned_docs/version-v0.19.0/language_concepts/data_types/10_function_types.md diff --git a/docs/versioned_docs/version-v0.19.0/migration_notes.md b/docs/versioned_docs/version-v0.19.0/migration_notes.md new file mode 100644 index 0000000000..0d7e0af0ef --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/migration_notes.md @@ -0,0 +1,91 @@ +--- +title: Migration notes +description: Read about migration notes from previous versions, which could solve problems while updating +keywords: [Noir, notes, migration, updating, upgrading] +--- + +Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. + +## ≥0.19 + +### Enforcing `compiler_version` + +From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. + +To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. + +## ≥0.14 + +The index of the [for loops](./language_concepts/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: + +```rust +for i in 0..10 { + let i = i as Field; +} +``` + +## ≥v0.11.0 and Nargo backend + +From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: + +### `backend encountered an error` + +This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. + +To fix the issue: + +1. Uninstall the existing backend + +```bash +nargo backend uninstall acvm-backend-barretenberg +``` + +You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. + +2. Reinstall a compatible version of the proving backend. + +If you are using the default barretenberg backend, simply run: + +``` +nargo prove +``` + +with you Noir program. + +This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. + +### `backend encountered an error: illegal instruction` + +On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. + +To fix the issue: + +1. Uninstall the existing backend + +```bash +nargo backend uninstall acvm-backend-barretenberg +``` + +You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. + +2. Reinstall a compatible version of the proving backend. + +If you are using the default barretenberg backend, simply run: + +``` +nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz +``` + +This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. + +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. + +Then run: + +``` +DESIRED_BINARY_VERSION=0.8.1 nargo info +``` + +This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. + +0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/docs/docs/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/crates_and_packages.md similarity index 100% rename from docs/docs/modules_packages_crates/crates_and_packages.md rename to docs/versioned_docs/version-v0.19.0/modules_packages_crates/crates_and_packages.md diff --git a/docs/docs/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md similarity index 100% rename from docs/docs/modules_packages_crates/dependencies.md rename to docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md diff --git a/docs/docs/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/modules.md similarity index 100% rename from docs/docs/modules_packages_crates/modules.md rename to docs/versioned_docs/version-v0.19.0/modules_packages_crates/modules.md diff --git a/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md new file mode 100644 index 0000000000..d9ac92667c --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md @@ -0,0 +1,39 @@ +--- +title: Workspaces +--- + +Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. + +Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. + +For a project with the following structure: + +```tree +├── crates +│   ├── a +│   │   ├── Nargo.toml +│   │   └── src +│   │   └── main.nr +│   └── b +│   ├── Nargo.toml +│   └── src +│   └── main.nr +├── Nargo.toml +└── Prover.toml +``` + +You can define a workspace in Nargo.toml like so: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. + +`default-member` indicates which package various commands process by default. + +Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/docs/docs/nargo/01_commands.md b/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md similarity index 100% rename from docs/docs/nargo/01_commands.md rename to docs/versioned_docs/version-v0.19.0/nargo/01_commands.md diff --git a/docs/docs/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.0/nargo/02_testing.md similarity index 100% rename from docs/docs/nargo/02_testing.md rename to docs/versioned_docs/version-v0.19.0/nargo/02_testing.md diff --git a/docs/docs/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.19.0/nargo/03_solidity_verifier.md similarity index 100% rename from docs/docs/nargo/03_solidity_verifier.md rename to docs/versioned_docs/version-v0.19.0/nargo/03_solidity_verifier.md diff --git a/docs/docs/nargo/04_language_server.md b/docs/versioned_docs/version-v0.19.0/nargo/04_language_server.md similarity index 100% rename from docs/docs/nargo/04_language_server.md rename to docs/versioned_docs/version-v0.19.0/nargo/04_language_server.md diff --git a/docs/docs/noir_js/getting_started/01_tiny_noir_app.md b/docs/versioned_docs/version-v0.19.0/noir_js/getting_started/01_tiny_noir_app.md similarity index 100% rename from docs/docs/noir_js/getting_started/01_tiny_noir_app.md rename to docs/versioned_docs/version-v0.19.0/noir_js/getting_started/01_tiny_noir_app.md diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/noir_js.md b/docs/versioned_docs/version-v0.19.0/noir_js/noir_js.md new file mode 100644 index 0000000000..23ea550e15 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/noir_js.md @@ -0,0 +1,36 @@ +--- +title: NoirJS +description: Interact with Noir in Typescript or Javascript +keywords: [Noir project, javascript, typescript, node.js, browser, react] +--- + +NoirJS is a TypeScript library that make it easy to use Noir on your dapp, webapp, Node.js server, website, etc. + +A typical workflow would be composed of two major elements: + +- NoirJS +- Proving backend of choice's JavaScript package + + + +To install NoirJS, install Node.js if you have not already and run this in your JavaScript project: + +```bash +npm i @noir-lang/noir_js +``` + +## Proving backend + +Since Noir is backend agnostic, you can instantiate NoirJS without any backend (i.e. to execute a function). But for proving, you would have to instantiate NoirJS with any of the supported backends through their own `js` interface. + +### Barretenberg + +Aztec Labs maintains the `barretenberg` proving backend, which you can instantiate and make use of alongside NoirJS. It is also the default proving backend installed and used with Nargo, the Noir CLI tool. + +To install its JavaScript library, run this in your project: + +```bash +npm i @noir-lang/backend_barretenberg +``` + +For more details on how to instantiate and use the libraries, refer to the [Full Noir App Guide](./getting_started/01_tiny_noir_app.md) and [Reference](./reference/01_noirjs.md) sections. diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md new file mode 100644 index 0000000000..ccdd53f2bc --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/01_noirjs.md @@ -0,0 +1,147 @@ +--- +title: Noir +description: Reference to noir_js library and the Noir class +keywords: [Noir project, javascript, typescript, node.js, browser, react, class, reference] +--- + +## Table of Contents + +- [constructor](#constructor) +- [init](#init) +- [generateFinalProof](#generatefinalproof) +- [verifyFinalProof](#verifyfinalproof) + +## `constructor` + +The `constructor` is a method used to create and initialize objects created within the `Noir` class. In the `Noir` class constructor, you need to pass two parameters: `circuit` and `backend`. + +### Syntax + +```js +constructor(circuit, backend); +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `circuit` | Object | A circuit represented in a `json` format, containing the ABI and bytecode. Typically obtained by running [`nargo compile`](../../nargo/01_commands.md) | +| `backend` | Object | A backend instance, before initialization. | + +### Usage + +```js +const noir = new Noir(circuit, backend); +``` + +## `init` + +This async method should be called after class instantiation. It will run processes on the ACVM, instantiate your backend, etc. + +### Syntax + +```js +async init() +``` + +### Parameters + +This method takes no parameters + +### Usage + +```js +await noirInstance.init(); +``` + +## `execute` + +This async method allows to execute a circuit to get its witness and return value. [`generateFinalProof`](#generatefinalproof) calls it for you, but you can call it directly (i.e. to feed directly to a backend, or to get the return value). + +You can optionally provide a foreignCallHandler, to handle functions that should run outside of the prover (e.g. `std::println`) + +### Syntax + +```js +async execute(inputs, foreignCallHandler) +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | ------ | ------------------------------------------------ | +| `inputs` | Object | An object containing the inputs to your circuit. | +| `foreignCallHandler` (optional) | Function | A function handling the foreign call from your circuit | + +### Returns + +| Return value | Type | Description | +| ------------ | --------------------- | --------------------------------------------------- | +| `witness` | Promise \ | The witness | +| `returnValue` | Promise \ | The return value | + +### Usage + +```js +const { witness, returnValue } = await noir.execute(inputs) +const { witness, returnValue } = await noir.execute(inputs, (name, args) => console.log(`Received foreign call ${name} with arguments ${args}`)) +``` + +## `generateFinalProof` + +This async method generates a witness and a proof given an object as input. + +### Syntax + +```js +async generateFinalproof(input) +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | ------ | ------------------------------------------------ | +| `input` | Object | An object containing the inputs to your circuit. | + +### Returns + +| Return value | Type | Description | +| ------------ | --------------------- | --------------------------------------------------- | +| `proof` | Promise \ | An array with the byte representation of the proof. | + +### Usage + +```js +// consider the Standard Noir Example given with nargo init +const input = { x: 1, y: 2 }; +noirInstance.generateProof(input); +``` + +## `verifyFinalProof` + +This async method instantiates the verification key and verifies your proof. + +### Syntax + +```js +async verifyFinalProof(proof) +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | ---------- | --------------------------------------------------------------------------------------------- | +| `proof` | Uint8Array | The Uint8Array representation of your proof, usually obtained by calling `generateFinalProof` | + +### Returns + +| Return value | Type | Description | +| ------------ | ------------------ | -------------------------------------------- | +| `verified` | Promise \ | A boolean for whether the proof was verified | + +### Usage + +```js +const proof = noirInstance.generateProof(input); +noirInstance.verifyFinalProof(proof); +``` diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md new file mode 100644 index 0000000000..f444eab177 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/02_bb_backend.md @@ -0,0 +1,272 @@ +--- +title: BarretenbergBackend +description: Reference documentation for the barretenberg_backend library and the BarretenbergBackend class +keywords: + [ + BarretenbergBackend, + Barretenberg, + javascript, + typescript, + node.js, + browser, + class, + reference, + noir_js, + ] +--- + +## Table of Contents + +- [constructor](#constructor) +- [generateFinalProof](#generatefinalproof) +- [generateIntermediateProof](#generateintermediateproof) +- [generateProof](#generateproof) +- [generateIntermediateProofArtifacts](#generateintermediateproofartifacts) +- [verifyFinalProof](#verifyfinalproof) +- [verifyIntermediateProof](#verifyintermediateproof) +- [verifyProof](#verifyproof) +- [destroy](#destroy) + +## `constructor` + +The `constructor` is a method used to create and initialize objects created within the `BarretenbergBackend` class. In this class, you should pass at least one argument for the `circuit`. + +### Syntax + +```js +constructor(acirCircuit, (numberOfThreads = 1)); +``` + +### Parameters + +| Parameter | Type | Description | +| ----------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `acirCircuit` | Object | A circuit represented in a `json` format, containing the ABI and bytecode Tipically obtained by running [`nargo compile`](../../nargo/01_commands.md). This is the same circuit expected to be passed to [the Noir class](01_noirjs.md) | +| `numberOfThreads` | Number (optional) | The number of threads to be used by the backend. Defaults to 1. | + +### Usage + +```js +const backend = new BarretenbergBackend(acirCircuit); +``` + +## `generateFinalProof` + +An async wrapper around the [generateProof](#generateproof) method that passes a `false` flag. Usually called by the Noir class. + +### Syntax + +```js +async generateFinalProof(decompressedWitness) +``` + +### Parameters + +| Parameter | Type | Description | +| --------------------- | ------ | -------------------------------------------------------- | +| `decompressedWitness` | Object | The decompressed witness for generating the final proof. | + +### Returns + +| Return value | Type | Description | +| ------------ | -------------------- | --------------------------------------------------------- | +| `proof` | Promise\ | An array with the byte representation of the final proof. | + +### Usage + +```js +const finalProof = await backend.generateFinalProof(decompressedWitness); +``` + +## `generateIntermediateProof` + +An async wrapper around the [generateProof](#generateproof) method that passes a `true` flag. It's not currently being used by the Noir class, but developers can call this method directly to use Noir's recursive features. + +### Syntax + +```js +async generateIntermediateProof(witness) +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | ------ | -------------------------------------------------- | +| `witness` | Object | The witness for generating the intermediate proof. | + +### Returns + +| Return value | Type | Description | +| ------------ | -------------------- | --------------------------------------------------------------- | +| `proof` | Promise\ | An array with the byte representation of the intermediate proof | + +### Usage + +```js +const intermediateProof = await backend.generateIntermediateProof(witness); +``` + +## `generateProof` + +This async method generates a proof. Takes the witness generated by ACVM, and a boolean that evaluates to `true` when the proof _is_ meant to be verified in another circuit. Not currently used by the Noir class. + +### Syntax + +```js +async generateProof(decompressedWitness, makeEasyToVerifyInCircuit) +``` + +### Parameters + +| Parameter | Type | Description | +| --------------------------- | ------- | ---------------------------------------------------------------------------------------------- | +| `decompressedWitness` | Object | The decompressed witness for generating the proof. | +| `makeEasyToVerifyInCircuit` | Boolean | A flag indicating whether to generate proof components for easy verification within a circuit. | + +### Returns + +| Return value | Type | Description | +| ------------ | -------------------- | -------------------------------------------------- | +| `proof` | Promise\ | An array with the byte representation of the proof | + +### Usage + +```js +const proof = await backend.generateProof(decompressedWitness, makeEasyToVerifyInCircuit); +``` + +## `generateIntermediateProofArtifacts` + +This async method returns the artifacts needed to verify the intermediate proof in another circuit. It's not currently being used by the Noir class, but developers can call this method directly to use Noir's recursive features. + +### Syntax + +```js +async generateIntermediateProofArtifacts(proof, numOfPublicInputs = 0) +``` + +### Parameters + +| Parameter | Type | Description | +| ------------------- | ----------------- | ---------------------------------------------------------------- | +| `proof` | Object | The proof object. | +| `numOfPublicInputs` | Number (optional) | The number of public inputs in the inner proof, defaulting to 0. | + +### Returns + +| Return value | Type | Description | +| --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `proofAsFields` | string[] | An array of strings with the hexadecimal representation of the [Fields](../../language_concepts/data_types/00_fields.md) that make up a proof | +| `vkAsFields` | string[] | An array of strings with the hexadecimal representation of the [Fields](../../language_concepts/data_types/00_fields.md) that make up the verification key | +| `vkHash` | string | A pedersen hash of the verification key | + +### Usage + +```js +const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); +``` + +## `verifyFinalProof` + +An async wrapper around [verifyProof](#verifyproof) that sets the `false` flag. Usually called by the Noir class. + +### Syntax + +```js +async verifyFinalProof(proof) +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | ------ | --------------------------- | +| `proof` | Object | The proof object to verify. | + +### Returns + +| Return value | Type | Description | +| ------------ | ------------------ | -------------------------------------------- | +| `verified` | Promise \ | A boolean for whether the proof was verified | + +### Usage + +```js +const isValidFinal = await backend.verifyFinalProof(proof); +``` + +## `verifyIntermediateProof` + +An async wrapper around [verifyProof](#verifyproof) that sets the `true` flag. It's not currently being used by the Noir class, but developers can call this method directly to use Noir's recursive features. + +### Syntax + +```js +async verifyIntermediateProof(proof) +``` + +### Parameters + +| Parameter | Type | Description | +| --------- | ------ | ---------------------------------------- | +| `proof` | Object | The intermediate proof object to verify. | + +### Returns + +| Return value | Type | Description | +| ------------ | ------------------ | -------------------------------------------- | +| `verified` | Promise \ | A boolean for whether the proof was verified | + +### Usage + +```js +const isValidIntermediate = await backend.verifyIntermediateProof(proof); +``` + +## `verifyProof` + +This async method verifies a proof. Takes the proof, and a boolean that evaluates to `true` when the proof is intermediate. + +### Syntax + +```js +async verifyProof(proof, makeEasyToVerifyInCircuit) +``` + +### Parameters + +| Parameter | Type | Description | +| --------------------------- | ------- | ------------------------------------------------------------ | +| `proof` | Object | The proof object to verify | +| `makeEasyToVerifyInCircuit` | Boolean | A flag indicating whether the proof is intermediate or final | + +### Returns + +| Parameter | Type | Description | +| ---------- | ------------------ | -------------------------------------------- | +| `verified` | Promise\ | A boolean for whether the proof was verified | + +### Usage + +```js +const isValid = await backend.verifyProof(proof, makeEasyToVerifyInCircuit); +``` + +## `destroy` + +This method destroys the resources allocated in the [instantiate](#instantiate) method. Noir doesn't currently call this method, but it's highly recommended that developers do so in order to save resources. + +### Syntax + +```js +async destroy() +``` + +### Parameters + +This method takes no parameters. + +### Usage + +```js +await backend.destroy(); +``` diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/.nojekyll new file mode 100644 index 0000000000..e2ac6616ad --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 0000000000..5cbe9421b9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,185 @@ +# BarretenbergBackend + +## Implements + +- [`Backend`](../interfaces/Backend.md) + +## Constructors + +### new BarretenbergBackend(acirCircuit, options) + +```ts +new BarretenbergBackend(acirCircuit, options): BarretenbergBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergBackend`](BarretenbergBackend.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(witness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `witness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) + +#### Example + +```typescript +const intermediateProof = await backend.generateIntermediateProof(witness); +``` + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) + +#### Example + +```typescript +const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) + +#### Example + +```typescript +const isValidIntermediate = await backend.verifyIntermediateProof(proof); +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/index.md new file mode 100644 index 0000000000..3680ba3ca7 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/index.md @@ -0,0 +1,27 @@ +# Backend Barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | + +### Interfaces + +| Interface | Description | +| :------ | :------ | +| [Backend](interfaces/Backend.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/interfaces/Backend.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/interfaces/Backend.md new file mode 100644 index 0000000000..3eb9645c8d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/interfaces/Backend.md @@ -0,0 +1,132 @@ +# Backend + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates an intermediate proof (meant to be verified in another circuit) + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | +| `numOfPublicInputs` | `number` | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Retrieves the artifacts from a proof in the Field format + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies an intermediate proof + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 0000000000..266ade75d1 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,19 @@ +# BackendOptions + +```ts +type BackendOptions: object; +``` + +## Description + +An options object, currently only used to specify the number of threads to use. + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `threads` | `number` | **Description**

Number of threads | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md new file mode 100644 index 0000000000..34e0dd0420 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

ABI representation of the circuit | +| `bytecode` | `string` | **Description**

The bytecode of the circuit | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md new file mode 100644 index 0000000000..4aeff73d3e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md @@ -0,0 +1,20 @@ +# ProofData + +```ts +type ProofData: object; +``` + +## Description + +The representation of a proof + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | +| `publicInputs` | `Uint8Array`[] | **Description**

Public inputs of a proof | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 0000000000..04e662c845 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/.nojekyll b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/.nojekyll new file mode 100644 index 0000000000..e2ac6616ad --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/classes/Noir.md new file mode 100644 index 0000000000..a8a0bb451c --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/classes/Noir.md @@ -0,0 +1,131 @@ +# Noir + +## Constructors + +### new Noir(circuit, backend) + +```ts +new Noir(circuit, backend?): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `backend`? | `Backend` | + +#### Returns + +[`Noir`](Noir.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the underlying backend instance. + +#### Example + +```typescript +await noir.destroy(); +``` + +*** + +### execute() + +```ts +execute(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | `InputMap` | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Allows to execute a circuit to get its witness and return value. + +#### Example + +```typescript +async execute(inputs) +``` + +*** + +### generateFinalProof() + +```ts +generateFinalProof(inputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | `InputMap` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a witness and a proof given an object as input. + +#### Example + +```typescript +async generateFinalproof(input) +``` + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Instantiates the verification key and verifies a proof. + +#### Example + +```typescript +async verifyFinalProof(proof) +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/and.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/and.md new file mode 100644 index 0000000000..c783283e39 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/blake2s256.md new file mode 100644 index 0000000000..7882d0da8d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 0000000000..0ba5783f0d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,29 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. +Verifies a ECDSA signature over the secp256k1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 0000000000..0b20ff6895 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/keccak256.md new file mode 100644 index 0000000000..d10f155ce8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/sha256.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/sha256.md new file mode 100644 index 0000000000..6ba4ecac02 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/xor.md new file mode 100644 index 0000000000..8d762b895d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/index.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/index.md new file mode 100644 index 0000000000..58902c17b9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/index.md @@ -0,0 +1,36 @@ +# Noir JS + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | +| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | +| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | +| [WitnessMap](type-aliases/WitnessMap.md) | - | + +### Functions + +| Function | Description | +| :------ | :------ | +| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | +| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | +| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | +| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | +| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | +| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | +| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md new file mode 100644 index 0000000000..34e0dd0420 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

ABI representation of the circuit | +| `bytecode` | `string` | **Description**

The bytecode of the circuit | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 0000000000..812b8b1648 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# ForeignCallHandler + +```ts +type ForeignCallHandler: (name, inputs) => Promise; +``` + +A callback which performs an foreign call and returns the response. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | The identifier for the type of foreign call being performed. | +| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | + +## Returns + +`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> + +outputs - An array of hex encoded outputs containing the results of the foreign call. + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 0000000000..dd95809186 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# ForeignCallInput + +```ts +type ForeignCallInput: string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 0000000000..b71fb78a94 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# ForeignCallOutput + +```ts +type ForeignCallOutput: string | string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ProofData.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ProofData.md new file mode 100644 index 0000000000..4aeff73d3e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/ProofData.md @@ -0,0 +1,20 @@ +# ProofData + +```ts +type ProofData: object; +``` + +## Description + +The representation of a proof + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | +| `publicInputs` | `Uint8Array`[] | **Description**

Public inputs of a proof | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 0000000000..258c46f9d0 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/typedoc-sidebar.cjs new file mode 100644 index 0000000000..c18318850d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/noir_js/reference/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"noir_js/reference/noir_js/functions/and","label":"and"},{"type":"doc","id":"noir_js/reference/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md new file mode 100644 index 0000000000..1dfabfe8f2 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md @@ -0,0 +1,46 @@ +--- +title: Black Box Functions +description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. +keywords: [noir, black box functions] +--- + +Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. + +:::warning + +It is likely that not all backends will support a particular black box function. + +::: + +Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. + +Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: + +```rust +#[foreign(sha256)] +fn sha256(_input : [u8; N]) -> [u8; 32] {} +``` + +## Function list + +Here is a list of the current black box functions that are supported by UltraPlonk: + +- AES +- [SHA256](./cryptographic_primitives/hashes#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr) +- [Blake2s](./cryptographic_primitives/hashes#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) +- [Compute merkle root](./merkle_trees#compute_merkle_root) +- AND +- XOR +- RANGE +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) + +Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. + +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). diff --git a/docs/docs/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives.md similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives.md rename to docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives.md diff --git a/docs/docs/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/00_hashes.mdx similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives/00_hashes.mdx rename to docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/00_hashes.mdx diff --git a/docs/docs/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/01_scalar.mdx similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives/01_scalar.mdx rename to docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/01_scalar.mdx diff --git a/docs/docs/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/02_schnorr.mdx similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives/02_schnorr.mdx rename to docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/02_schnorr.mdx diff --git a/docs/docs/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx rename to docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx diff --git a/docs/docs/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/04_ec_primitives.md similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives/04_ec_primitives.md rename to docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/04_ec_primitives.md diff --git a/docs/docs/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/05_eddsa.mdx similarity index 100% rename from docs/docs/standard_library/cryptographic_primitives/05_eddsa.mdx rename to docs/versioned_docs/version-v0.19.0/standard_library/cryptographic_primitives/05_eddsa.mdx diff --git a/docs/docs/standard_library/logging.md b/docs/versioned_docs/version-v0.19.0/standard_library/logging.md similarity index 100% rename from docs/docs/standard_library/logging.md rename to docs/versioned_docs/version-v0.19.0/standard_library/logging.md diff --git a/docs/docs/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.19.0/standard_library/merkle_trees.md similarity index 100% rename from docs/docs/standard_library/merkle_trees.md rename to docs/versioned_docs/version-v0.19.0/standard_library/merkle_trees.md diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/options.md b/docs/versioned_docs/version-v0.19.0/standard_library/options.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/standard_library/options.md rename to docs/versioned_docs/version-v0.19.0/standard_library/options.md diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/recursion.md b/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/standard_library/recursion.md rename to docs/versioned_docs/version-v0.19.0/standard_library/recursion.md diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/zeroed.md b/docs/versioned_docs/version-v0.19.0/standard_library/zeroed.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/standard_library/zeroed.md rename to docs/versioned_docs/version-v0.19.0/standard_library/zeroed.md diff --git a/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md index 725c5f4d37..349756d60c 100644 --- a/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noi ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation diff --git a/docs/versioned_docs/version-v0.19.1/index.md b/docs/versioned_docs/version-v0.19.1/index.md index 75e1abf293..4e2f404389 100644 --- a/docs/versioned_docs/version-v0.19.1/index.md +++ b/docs/versioned_docs/version-v0.19.1/index.md @@ -67,7 +67,7 @@ Compiler: - For expressions - Arrays - Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] - Unsigned integers - If statements - Structures and Tuples diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.19.1/language_concepts/01_functions.md index 47cdea0cf0..5eb22170e5 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/01_functions.md +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/01_functions.md @@ -30,7 +30,7 @@ All parameters in a function must have a type and all types are known at compile is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. ```rust -fn foo(x : Field, y : pub Field){} +fn foo(x : Field, y : Field){} ``` The return type of a function can be stated by using the `->` arrow notation. The function below @@ -38,7 +38,7 @@ states that the foo function must return a `Field`. If the function returns no v is omitted. ```rust -fn foo(x : Field, y : pub Field) -> Field { +fn foo(x : Field, y : Field) -> Field { x + y } ``` diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md index da02b12605..d5caa46376 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.19.1/language_concepts/07_mutability.md index 4641521b1d..ad902c42c9 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/07_mutability.md +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/07_mutability.md @@ -37,7 +37,7 @@ Note that mutability in noir is local and everything is passed by value, so if a mutates its parameters then the parent function will keep the old value of the parameters. ```rust -fn main() -> Field { +fn main() -> pub Field { let x = 3; helper(x); x // x is still 3 diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md index 658a0441ff..78d3d2af16 100644 --- a/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md @@ -158,7 +158,7 @@ fn main() { ### sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versioned_docs/version-v0.19.1/migration_notes.md b/docs/versioned_docs/version-v0.19.1/migration_notes.md index e87eb1feab..0d7e0af0ef 100644 --- a/docs/versioned_docs/version-v0.19.1/migration_notes.md +++ b/docs/versioned_docs/version-v0.19.1/migration_notes.md @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running this bash script: , where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md index 725c5f4d37..349756d60c 100644 --- a/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md +++ b/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md @@ -14,7 +14,7 @@ Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noi ### UltraPlonk -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. ## Installation diff --git a/docs/versioned_docs/version-v0.19.2/index.md b/docs/versioned_docs/version-v0.19.2/index.md index 75e1abf293..4e2f404389 100644 --- a/docs/versioned_docs/version-v0.19.2/index.md +++ b/docs/versioned_docs/version-v0.19.2/index.md @@ -67,7 +67,7 @@ Compiler: - For expressions - Arrays - Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] - Unsigned integers - If statements - Structures and Tuples diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.19.2/language_concepts/01_functions.md index 47cdea0cf0..5eb22170e5 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/01_functions.md +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/01_functions.md @@ -30,7 +30,7 @@ All parameters in a function must have a type and all types are known at compile is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. ```rust -fn foo(x : Field, y : pub Field){} +fn foo(x : Field, y : Field){} ``` The return type of a function can be stated by using the `->` arrow notation. The function below @@ -38,7 +38,7 @@ states that the foo function must return a `Field`. If the function returns no v is omitted. ```rust -fn foo(x : Field, y : pub Field) -> Field { +fn foo(x : Field, y : Field) -> Field { x + y } ``` diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md index da02b12605..d5caa46376 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md @@ -29,11 +29,11 @@ keywords: | ^ | XOR two private input types together | Types must be integer | | & | AND two private input types together | Types must be integer | | \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | | >> | Right shift an integer by another integer amount | Types must be integer | | ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | | > | returns a bool if one value is more than the other | Upper bound must have a known bit size | | >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | | == | returns a bool if one value is equal to the other | Both types must not be constants | diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.19.2/language_concepts/07_mutability.md index 4641521b1d..ad902c42c9 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/07_mutability.md +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/07_mutability.md @@ -37,7 +37,7 @@ Note that mutability in noir is local and everything is passed by value, so if a mutates its parameters then the parent function will keep the old value of the parameters. ```rust -fn main() -> Field { +fn main() -> pub Field { let x = 3; helper(x); x // x is still 3 diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md index 658a0441ff..78d3d2af16 100644 --- a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md @@ -158,7 +158,7 @@ fn main() { ### sgn0 -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. ```rust fn sgn0(self) -> u1 diff --git a/docs/versioned_docs/version-v0.19.2/migration_notes.md b/docs/versioned_docs/version-v0.19.2/migration_notes.md index e87eb1feab..0d7e0af0ef 100644 --- a/docs/versioned_docs/version-v0.19.2/migration_notes.md +++ b/docs/versioned_docs/version-v0.19.2/migration_notes.md @@ -78,7 +78,7 @@ nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/bar This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. -The gzipped filed is running this bash script: , where we need to gzip it as the Nargo currently expect the backend to be zipped up. +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. Then run: diff --git a/docs/versioned_docs/version-v0.19.3/examples/merkle-proof.mdx b/docs/versioned_docs/version-v0.19.3/examples/merkle-proof.mdx new file mode 100644 index 0000000000..832fb4bb55 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/examples/merkle-proof.mdx @@ -0,0 +1,48 @@ +--- +title: Merkle Proof Membership +description: + Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a + merkle tree with a specified root, at a given index. +keywords: + [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +--- + +Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is +in a merkle tree. + +```rust +use dep::std; + +fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { + let leaf = std::hash::hash_to_field(message); + let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); + assert(merkle_root == root); +} + +``` + +The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen +by the backend. The only requirement is that this hash function can heuristically be used as a +random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` +instead. + +```rust +let leaf = std::hash::hash_to_field(message); +``` + +The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. + +```rust +let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); +assert (merkle_root == root); +``` + +> **Note:** It is possible to re-implement the merkle tree implementation without standard library. +> However, for most usecases, it is enough. In general, the standard library will always opt to be +> as conservative as possible, while striking a balance with efficiency. + +An example, the merkle membership proof, only requires a hash function that has collision +resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient +than the even more conservative sha256. + +[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md new file mode 100644 index 0000000000..349756d60c --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/getting_started/00_nargo_installation.md @@ -0,0 +1,249 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, + verifying and more). Learn how to install and use Nargo for your projects with this comprehensive + guide. +keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] +--- + +`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, +verifying and more). + +Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noir_js.md). + +### UltraPlonk + +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. + +## Installation + +There are four approaches for installing Nargo: + +- [Option 1: Noirup](#option-1-noirup) +- [Option 2: Binaries](#option-2-binaries) +- [Option 3: Compile from Source](#option-3-compile-from-source) +- [Option 4: WSL for Windows](#option-4-wsl-for-windows) + +Optionally you can also install [Noir VS Code extension] for syntax highlighting. + +### Option 1: Noirup + +If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a +terminal and run: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done, you should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. + +#### GitHub Actions + +You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as +installing `noirup` and running tests in your GitHub Action `yml` file. + +See the +[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in +this repo containing hash functions in Noir for an example. + +#### Nightly versions + +To install the nightly version of Noir (updated daily) run: + +```bash +noirup -n +``` + +### Option 2: Binaries + +See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous +platform specific binaries. + +#### Step 1 + +Paste and run the following in the terminal to extract and install the binary: + +> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend +> `sudo` and re-run it. + +##### macOS (Apple Silicon) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ +echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ +source ~/.zshrc +``` + +##### macOS (Intel) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ +echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ +source ~/.zshrc +``` + +##### Linux (Bash) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ +echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ +source ~/.bashrc +``` + +#### Step 2 + +Check if the installation was successful by running `nargo --help`. + +> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from +> Finder. Close the new terminal popped up and `nargo` should now be accessible. + +For a successful installation, you should see something similar to the following after running the +command: + +```sh +$ nargo --help + +Noir's package manager + +Usage: nargo + +Commands: + check Checks the constraint system for errors + codegen-verifier Generates a Solidity verifier smart contract for the program + compile Compile the program and its secret execution trace into ACIR format + new Create a new binary project + execute Executes a circuit to calculate its return value + prove Create proof for this program. The proof is returned as a hex encoded string + verify Given a proof and a program, verify whether the proof is valid + test Run the tests for this program + gates Counts the occurrences of different gates in circuit + help Print this message or the help of the given subcommand(s) +``` + +### Option 3: Compile from Source + +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). + +Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. + +#### Setting up your environment + +For the best experience, please follow these instructions to setup your environment: + +1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. +2. Create the file `~/.config/nix/nix.conf` with the contents: + +```ini +experimental-features = nix-command +extra-experimental-features = flakes +``` + +3. Install direnv into your Nix profile by running: + +```sh +nix profile install nixpkgs#direnv +``` + +4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). + 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. +5. Restart your shell. + +#### Shell & editor experience + +Now that your environment is set up, you can get to work on the project. + +1. Clone the repository, such as: + +```sh +git clone git@github.com:noir-lang/noir +``` + +> Replacing `noir` with whichever repository you want to work on. + +2. Navigate to the directory: + +```sh +cd noir +``` + +> Replacing `noir` with whichever repository you cloned. + +3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: + +```sh +direnv allow +``` + +4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. + +5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): + +```sh +code . +``` + +6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. + +#### Building and testing + +Assuming you are using `direnv` to populate your environment, building and testing the project can be done +with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. + +If you want to build the entire project in an isolated sandbox, you can use Nix commands: + +1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. +2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. + +#### Without `direnv` + +If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. + +Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! + +### Option 4: WSL (for Windows) + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). + +Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. + +step 2: Follow the [Noirup instructions](#option-1-noirup). + +## Uninstalling Nargo + +### Noirup + +If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` + +### Nix + +If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. + +```bash +rm ~/.nix-profile/bin/nargo +``` + +[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/docs/versioned_docs/version-v0.10.5/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/getting_started/01_hello_world.md rename to docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md diff --git a/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md new file mode 100644 index 0000000000..9a17f5d636 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md @@ -0,0 +1,198 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML + files, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] +--- + +This section breaks down our hello world program in section _1.2_. We elaborate on the project +structure and what the `prove` and `verify` commands did in the previous section. + +## Anatomy of a Nargo Project + +Upon creating a new project with `nargo new` and building the in/output files with `nargo check` +commands, you would get a minimal Nargo project of the following structure: + + - src + - Prover.toml + - Verifier.toml + - Nargo.toml + +The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ +file will be generated within it. + +### Prover.toml + +_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. + +### Verifier.toml + +_Verifier.toml_ contains public in/output values computed when executing the Noir program. + +### Nargo.toml + +_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. + +Example Nargo.toml: + +```toml +[package] +name = "noirstarter" +type = "bin" +authors = ["Alice"] +compiler_version = "0.9.0" +description = "Getting started with Noir" +entry = "circuit/main.nr" +license = "MIT" + +[dependencies] +ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} +``` + +Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +#### Package section + +The package section requires a number of fields including: + +- `name` (**required**) - the name of the package +- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract +- `authors` (optional) - authors of the project +- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) +- `description` (optional) +- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) +- `backend` (optional) +- `license` (optional) + +#### Dependencies section + +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. + +`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or +verifier contract respectively. + +### main.nr + +The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. + +In our sample program, _main.nr_ looks like this: + +```rust +fn main(x : Field, y : Field) { + assert(x != y); +} +``` + +The parameters `x` and `y` can be seen as the API for the program and must be supplied by the +prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when +verifying the proof. + +The prover supplies the values for `x` and `y` in the _Prover.toml_ file. + +As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is +constrained by the proof of the execution of said program (i.e. if the condition was not met, the +verifier would reject the proof as an invalid proof). + +### Prover.toml + +The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and +public). + +In our hello world program the _Prover.toml_ file looks like this: + +```toml +x = "1" +y = "2" +``` + +When the command `nargo prove` is executed, two processes happen: + +1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` + is not equal. This not equal constraint is due to the line `assert(x != y)`. + +2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. + +#### Arrays of Structs + +The following code shows how to pass an array of structs to a Noir program to generate a proof. + +```rust +// main.nr +struct Foo { + bar: Field, + baz: Field, +} + +fn main(foos: [Foo; 3]) -> pub Field { + foos[2].bar + foos[2].baz +} +``` + +Prover.toml: + +```toml +[[foos]] # foos[0] +bar = 0 +baz = 0 + +[[foos]] # foos[1] +bar = 0 +baz = 0 + +[[foos]] # foos[2] +bar = 1 +baz = 2 +``` + +#### Custom toml files + +You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. + +This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: + +```bash +nargo prove +``` + +This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: + +```bash +nargo prove -p OtherProver +``` + +## Verifying a Proof + +When the command `nargo verify` is executed, two processes happen: + +1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) + +2. If that file is found, the proof's validity is checked + +> **Note:** The validity of the proof is linked to the current Noir program; if the program is +> changed and the verifier verifies the proof, it will fail because the proof is not valid for the +> _modified_ Noir program. + +In production, the prover and the verifier are usually two separate entities. A prover would +retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the +verifier. The verifier would then retrieve the public inputs from usually external sources and +verifies the validity of the proof against it. + +Take a private asset transfer as an example: + +A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and +public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof +and submit it to the verifier smart contract. + +The verifier contract would then draw the user's encrypted balance directly from the blockchain and +verify the proof submitted against it. If the verification passes, additional functions in the +verifier contract could trigger (e.g. approve the asset transfer). + +Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/docs/versioned_docs/version-v0.19.3/index.md b/docs/versioned_docs/version-v0.19.3/index.md new file mode 100644 index 0000000000..4e2f404389 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/index.md @@ -0,0 +1,100 @@ +--- +title: Introducing Noir +description: + Learn about the public alpha release of Noir, a domain specific language heavily influenced by + Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a + rank-1 constraint system. +keywords: + [ + Noir, + Domain Specific Language, + Rust, + Intermediate Language, + Arithmetic Circuit, + Rank-1 Constraint System, + Ethereum Developers, + Protocol Developers, + Blockchain Developers, + Proving System, + Smart Contract Language, + ] +slug: / +--- + +## What is Noir? + +Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. + +It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. + +## Who is Noir for? + +Noir can be used for a variety of purposes. + +### Solidity Developers + +Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will +be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +a verifier contract. + +### Protocol Developers + +As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for +your stack, or maybe you simply want to use a different proving system. Since Noir does not compile +to a specific proof system, it is possible for protocol developers to replace the PLONK-based +proving system with a different proving system altogether. + +### Blockchain developers + +As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the +proving system and smart contract language has been pre-defined). In order for you to use Noir in +your blockchain, a proving system backend and a smart contract interface +must be implemented for it. + +## What's new about Noir? + +Noir is simple and flexible in its design, as it does not compile immediately to a fixed +NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled +to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). + +This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. + +## Current Features + +Compiler: + +- Module System +- For expressions +- Arrays +- Bit Operations +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Unsigned integers +- If statements +- Structures and Tuples +- Generics + +ACIR Supported OPCODES: + +- Sha256 +- Blake2s +- Schnorr signature verification +- MerkleMembership +- Pedersen Commitment +- Pedersen Hash +- HashToField + +## Libraries + +Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). + +Some libraries that are available today include: + +- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library +- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) +- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers +- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address +- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees +- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir +- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers + +See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.19.3/language_concepts/01_functions.md new file mode 100644 index 0000000000..5eb22170e5 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/01_functions.md @@ -0,0 +1,225 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](../nargo/02_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main([1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./06_generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./08_lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](../noir_js/noir_js.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../nargo/02_testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.19.3/language_concepts/02_control_flow.md new file mode 100644 index 0000000000..a7f8536019 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/02_control_flow.md @@ -0,0 +1,44 @@ +--- +title: Control Flow +description: + Learn how to use loops and if expressions in the Noir programming language. Discover the syntax + and examples for for loops and if-else statements. +keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +--- + +## Loops + +Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple +times. + +The following block of code between the braces is run 10 times. + +```rust +for i in 0..10 { + // do something +}; +``` + +The index for loops is of type `u64`. + +## If Expressions + +Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required +for the statement's conditional to be surrounded by parentheses. + +```rust +let a = 0; +let mut x: u32 = 0; + +if a == 0 { + if a != 0 { + x = 6; + } else { + x = 2; + } +} else { + x = 5; + assert(x == 5); +} +assert(x == 2); +``` diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md new file mode 100644 index 0000000000..d5caa46376 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/03_ops.md @@ -0,0 +1,97 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | +| >> | Right shift an integer by another integer amount | Types must be integer | +| ! | Bitwise not of a value | Type must be integer or boolean | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | +| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | +| == | returns a bool if one value is equal to the other | Both types must not be constants | +| != | returns a bool if one value is not equal to the other | Both types must not be constants | + +### Predicate Operators + +`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. +This differs from the operations such as `+` where the operands are used in _computation_. + +### Bitwise Operations Example + +```rust +fn main(x : Field) { + let y = x as u32; + let z = y & y; +} +``` + +`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise +`&`. + +> `x & x` would not compile as `x` is a `Field` and not an integer type. + +### Logical Operators + +Noir has no support for the logical operators `||` and `&&`. This is because encoding the +short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can +use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +short-circuiting. + +```rust +let my_val = 5; + +let mut flag = 1; +if (my_val > 6) | (my_val == 0) { + flag = 0; +} +assert(flag == 1); + +if (my_val != 10) & (my_val < 50) { + flag = 0; +} +assert(flag == 0); +``` + +### Shorthand operators + +Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: + +```rust +let mut i = 0; +i = i + 1; +``` + +could be written as: + +```rust +let mut i = 0; +i += 1; +``` diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.19.3/language_concepts/04_assert.md new file mode 100644 index 0000000000..7427ec6cc6 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/04_assert.md @@ -0,0 +1,26 @@ +--- +title: Assert Function +description: + Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or + comparison expression that follows to be true, and what happens if the expression is false at + runtime. +keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +--- + +Noir includes a special `assert` function which will explicitly constrain the predicate/comparison +expression that follows to be true. If this expression is false at runtime, the program will fail to +be proven. Example: + +```rust +fn main(x : Field, y : Field) { + assert(x == y); +} +``` + +You can optionally provide a message to be logged when the assertion fails: + +```rust +assert(x == y, "x and y are not equal"); +``` + +> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.19.3/language_concepts/05_unconstrained.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/language_concepts/05_unconstrained.md rename to docs/versioned_docs/version-v0.19.3/language_concepts/05_unconstrained.md diff --git a/docs/docs/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.19.3/language_concepts/06_generics.md similarity index 100% rename from docs/docs/language_concepts/06_generics.md rename to docs/versioned_docs/version-v0.19.3/language_concepts/06_generics.md diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.19.3/language_concepts/07_mutability.md new file mode 100644 index 0000000000..ad902c42c9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/07_mutability.md @@ -0,0 +1,92 @@ +--- +title: Mutability +description: + Learn about mutable variables, constants, and globals in Noir programming language. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Comptime Values + +:::warning + +The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. + +::: + +## Globals + +Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array +annotations for function parameters and can be imported from submodules. + +```rust +global N: Field = 5; // Same as `global N: Field = 5` + +fn main(x : Field, y : [Field; N]) { + let res = x * N; + + assert(res == y[0]); + + let res2 = x * mysubmodule::N; + assert(res != res2); +} + +mod mysubmodule { + use dep::std; + + global N: Field = 10; + + fn my_helper() -> Field { + let x = N; + x + } +} +``` + +## Why only local mutability? + +Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting +without applying additional overhead to the user. Modeling a mutable reference is not as +straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/08_lambdas.md b/docs/versioned_docs/version-v0.19.3/language_concepts/08_lambdas.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/language_concepts/08_lambdas.md rename to docs/versioned_docs/version-v0.19.3/language_concepts/08_lambdas.md diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/09_comments.md b/docs/versioned_docs/version-v0.19.3/language_concepts/09_comments.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/language_concepts/09_comments.md rename to docs/versioned_docs/version-v0.19.3/language_concepts/09_comments.md diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/10_distinct.md b/docs/versioned_docs/version-v0.19.3/language_concepts/10_distinct.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/language_concepts/10_distinct.md rename to docs/versioned_docs/version-v0.19.3/language_concepts/10_distinct.md diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/11_shadowing.md b/docs/versioned_docs/version-v0.19.3/language_concepts/11_shadowing.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/language_concepts/11_shadowing.md rename to docs/versioned_docs/version-v0.19.3/language_concepts/11_shadowing.md diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/language_concepts/data_types.md rename to docs/versioned_docs/version-v0.19.3/language_concepts/data_types.md diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/00_fields.md new file mode 100644 index 0000000000..78d3d2af16 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/00_fields.md @@ -0,0 +1,165 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_le_bits(32); +} +``` + +### to_be_bits + +Transforms the field into an array of bits, Big Endian. + +```rust +fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_be_bits(32); +} +``` + +### to_le_bytes + +Transforms into an array of bytes, Little Endian + +```rust +fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_le_bytes(4); +} +``` + +### to_be_bytes + +Transforms into an array of bytes, Big Endian + +```rust +fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_be_bytes(4); +} +``` + +### to_le_radix + +Decomposes into a vector over the specified base, Little Endian + +```rust +fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_le_radix(256, 4); +} +``` + +### to_be_radix + +Decomposes into a vector over the specified base, Big Endian + +```rust +fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_be_radix(256, 4); +} +``` + +### pow_32 + +Returns the value to the power of the specified exponent + +```rust +fn pow_32(self, exponent: Field) -> Field +``` + +example: + +```rust +fn main() { + let field = 2 + let pow = field.pow_32(4); + assert(pow == 16); +} +``` + +### sgn0 + +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. + +```rust +fn sgn0(self) -> u1 +``` diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/01_integers.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/01_integers.md new file mode 100644 index 0000000000..b1e7ad11bf --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/01_integers.md @@ -0,0 +1,112 @@ +--- +title: Integers +description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. +keywords: [noir, integer types, methods, examples, arithmetic] +--- + +An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. + +:::info + +When an integer is defined in Noir without a specific type, it will default to `Field`. + +The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. + +::: + +## Unsigned Integers + +An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): + +```rust +fn main() { + let x: u8 = 1; + let y: u8 = 1; + let z = x + y; + assert (z == 2); +} +``` + +The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). + +## Signed Integers + +A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): + +```rust +fn main() { + let x: i8 = -1; + let y: i8 = -1; + let z = x + y; + assert (z == -2); +} +``` + +The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). + +:::tip + +If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. + +::: + +## Overflows + +Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: + +```rust +fn main(x: u8, y: u8) { + let z = x + y; +} +``` + +With: + +```toml +x = "255" +y = "1" +``` + +Would result in: + +``` +$ nargo prove +error: Assertion failed: 'attempt to add with overflow' +┌─ ~/src/main.nr:9:13 +│ +│ let z = x + y; +│ ----- +│ += Call stack: + ... +``` + +A similar error would happen with signed integers: + +```rust +fn main() { + let x: i8 = -118; + let y: i8 = -11; + let z = x + y; +} +``` + +### Wrapping methods + +Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: + +```rust +fn wrapping_add(x: T, y: T) -> T; +fn wrapping_sub(x: T, y: T) -> T; +fn wrapping_mul(x: T, y: T) -> T; +``` + +Example of how it is used: + +```rust +use dep::std; + +fn main(x: u8, y: u8) -> pub u8 { + std::wrapping_add(x + y) +} +``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/language_concepts/data_types/02_booleans.md rename to docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md new file mode 100644 index 0000000000..c42f34ec3a --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md @@ -0,0 +1,63 @@ +--- +title: Strings +description: + Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. +keywords: + [ + noir, + string type, + methods, + examples, + concatenation, + ] +--- + + +The string type is a fixed length value defined with `str`. + +You can use strings in `assert()` functions or print them with +`std::println()`. See more about [Logging](../../standard_library/logging). + +```rust +use dep::std; + +fn main(message : pub str<11>, hex_as_string : str<4>) { + std::println(message); + assert(message == "hello world"); + assert(hex_as_string == "0x41"); +} +``` + +You can convert a `str` to a byte array by calling `as_bytes()` +or a vector by calling `as_bytes_vec()`. + +```rust +fn main() { + let message = "hello world"; + let message_bytes = message.as_bytes(); + let mut message_vec = message.as_bytes_vec(); + assert(message_bytes.len() == 11); + assert(message_bytes[0] == 104); + assert(message_bytes[0] == message_vec.get(0)); +} +``` + +## Escape characters + +You can use escape characters for your strings: + +| Escape Sequence | Description | +|-----------------|-----------------| +| `\r` | Carriage Return | +| `\n` | Newline | +| `\t` | Tab | +| `\0` | Null Character | +| `\"` | Double Quote | +| `\\` | Backslash | + +Example: + +```rust +let s = "Hello \"world" // prints "Hello "world" +let s = "hey \tyou"; // prints "hey you" +``` diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md new file mode 100644 index 0000000000..bdbd1798be --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md @@ -0,0 +1,244 @@ +--- +title: Arrays +description: + Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. +keywords: + [ + noir, + array type, + methods, + examples, + indexing, + ] +--- + +An array is one way of grouping together values into one compound type. Array types can be inferred +or explicitly specified via the syntax `[; ]`: + +```rust +fn main(x : Field, y : Field) { + let my_arr = [x, y]; + let your_arr: [Field; 2] = [x, y]; +} +``` + +Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. + +Array elements can be accessed using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group +a `Field` value and a `u8` value together for example. + +You can write mutable arrays, like: + +```rust +fn main() { + let mut arr = [1, 2, 3, 4, 5]; + assert(arr[0] == 1); + + arr[0] = 42; + assert(arr[0] == 42); +} +``` + +You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. + +```rust +let array: [Field; 32] = [0; 32]; +``` + +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: + +```rust +let array: [Field; 32] = [0; 32]; +let sl = array.as_slice() +``` + +You can define multidimensional arrays: + +```rust +let array : [[Field; 2]; 2]; +let element = array[0][0]; +``` + +## Types + +You can create arrays of primitive types or structs. There is not yet support for nested arrays +(arrays of arrays) or arrays of structs that contain arrays. + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for arrays: + +### len + +Returns the length of an array + +```rust +fn len(_array: [T; N]) -> comptime Field +``` + +example + +```rust +fn main() { + let array = [42, 42]; + assert(array.len() == 2); +} +``` + +### sort + +Returns a new sorted array. The original array remains untouched. Notice that this function will +only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting +logic it uses internally is optimized specifically for these values. If you need a sort function to +sort any type, you should use the function `sort_via` described below. + +```rust +fn sort(_array: [T; N]) -> [T; N] +``` + +example + +```rust +fn main() { + let arr = [42, 32]; + let sorted = arr.sort(); + assert(sorted == [32, 42]); +} +``` + +### sort_via + +Sorts the array with a custom comparison function + +```rust +fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] +``` + +example + +```rust +fn main() { + let arr = [42, 32] + let sorted_ascending = arr.sort_via(|a, b| a < b); + assert(sorted_ascending == [32, 42]); // verifies + + let sorted_descending = arr.sort_via(|a, b| a > b); + assert(sorted_descending == [32, 42]); // does not verify +} +``` + +### map + +Applies a function to each element of the array, returning a new array containing the mapped elements. + +```rust +fn map(f: fn(T) -> U) -> [U; N] +``` + +example + +```rust +let a = [1, 2, 3]; +let b = a.map(|a| a * 2); // b is now [2, 4, 6] +``` + +### fold + +Applies a function to each element of the array, returning the final accumulated value. The first +parameter is the initial value. + +```rust +fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U +``` + +This is a left fold, so the given function will be applied to the accumulator and first element of +the array, then the second, and so on. For a given call the expected result would be equivalent to: + +```rust +let a1 = [1]; +let a2 = [1, 2]; +let a3 = [1, 2, 3]; + +let f = |a, b| a - b; +a1.fold(10, f) //=> f(10, 1) +a2.fold(10, f) //=> f(f(10, 1), 2) +a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) +``` + +example: + +```rust + +fn main() { + let arr = [2, 2, 2, 2, 2]; + let folded = arr.fold(0, |a, b| a + b); + assert(folded == 10); +} + +``` + +### reduce + +Same as fold, but uses the first element as starting element. + +```rust +fn reduce(f: fn(T, T) -> T) -> T +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 2]; + let reduced = arr.reduce(|a, b| a + b); + assert(reduced == 10); +} +``` + +### all + +Returns true if all the elements satisfy the given predicate + +```rust +fn all(predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 2]; + let all = arr.all(|a| a == 2); + assert(all); +} +``` + +### any + +Returns true if any of the elements satisfy the given predicate + +```rust +fn any(predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 5]; + let any = arr.any(|a| a == 5); + assert(any); +} + +``` diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/05_slices.mdx b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/05_slices.mdx new file mode 100644 index 0000000000..1be0ec4a13 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/05_slices.mdx @@ -0,0 +1,146 @@ +--- +title: Slices +description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. +keywords: [noir, slice type, methods, examples, subarrays] +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. + +```rust +use dep::std::slice; + +fn main() -> pub Field { + let mut slice: [Field] = [0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for slices: + +### push_back + +Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. + +```rust +fn push_back(_self: [T], _elem: T) -> [T] +``` + +example: + +```rust +fn main() -> pub Field { + let mut slice: [Field] = [0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +### push_front + +Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. + +```rust +fn push_front(_self: Self, _elem: T) -> Self +``` + +Example: + +```rust +let mut new_slice: [Field] = []; +new_slice = new_slice.push_front(20); +assert(new_slice[0] == 20); // returns true +``` + +View the corresponding test file [here][test-file]. + +### pop_front + +Returns a tuple of two items, the first element of the array and the rest of the array. + +```rust +fn pop_front(_self: Self) -> (T, Self) +``` + +Example: + +```rust +let (first_elem, rest_of_slice) = slice.pop_front(); +``` + +View the corresponding test file [here][test-file]. + +### pop_back + +Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. + +```rust +fn pop_back(_self: Self) -> (Self, T) +``` + +Example: + +```rust +let (popped_slice, last_elem) = slice.pop_back(); +``` + +View the corresponding test file [here][test-file]. + +### append + +Loops over a slice and adds it to the end of another. + +```rust +fn append(mut self, other: Self) -> Self +``` + +Example: + +```rust +let append = [1, 2].append([3, 4, 5]); +``` + +### insert + +Inserts an element at a specified index and shifts all following elements by 1. + +```rust +fn insert(_self: Self, _index: Field, _elem: T) -> Self +``` + +Example: + +```rust +new_slice = rest_of_slice.insert(2, 100); +assert(new_slice[2] == 100); +``` + +View the corresponding test file [here][test-file]. + +### remove + +Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. + +```rust +fn remove(_self: Self, _index: Field) -> (Self, T) +``` + +Example: + +```rust +let (remove_slice, removed_elem) = slice.remove(3); +``` diff --git a/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/06_vectors.mdx b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/06_vectors.mdx new file mode 100644 index 0000000000..4617e90d03 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/06_vectors.mdx @@ -0,0 +1,172 @@ +--- +title: Vectors +description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. +keywords: [noir, vector type, methods, examples, dynamic arrays] +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. + +Example: + +```rust +use dep::std::collections::vec::Vec; + +let mut vector: Vec = Vec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +``` + +## Methods + +### new + +Creates a new, empty vector. + +```rust +pub fn new() -> Self { + Self { slice: [] } +} +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### from_slice + +Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. + +```rust +pub fn from_slice(slice: [T]) -> Self { + Self { slice } +} +``` + +Example: + +```rust +let arr: [Field] = [1, 2, 3]; +let vector_from_slice = Vec::from_slice(arr); +assert(vector_from_slice.len() == 3); +``` + +### get + +Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. + +```rust +pub fn get(self, index: Field) -> T { + self.slice[index] +} +``` + +Example: + +```rust +let vector: Vec = Vec::from_slice([10, 20, 30]); +assert(vector.get(1) == 20); +``` + +### push + +Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. + +```rust +pub fn push(&mut self, elem: T) { + self.slice = self.slice.push_back(elem); +} +``` + +Example: + +```rust +let mut vector: Vec = Vec::new(); +vector.push(10); +assert(vector.len() == 1); +``` + +### pop + +Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. + +```rust +pub fn pop(&mut self) -> T { + let (popped_slice, last_elem) = self.slice.pop_back(); + self.slice = popped_slice; + last_elem +} +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 20]); +let popped_elem = vector.pop(); +assert(popped_elem == 20); +assert(vector.len() == 1); +``` + +### insert + +Inserts an element at a specified index, shifting subsequent elements to the right. + +```rust +pub fn insert(&mut self, index: Field, elem: T) { + self.slice = self.slice.insert(index, elem); +} +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 30]); +vector.insert(1, 20); +assert(vector.get(1) == 20); +``` + +### remove + +Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. + +```rust +pub fn remove(&mut self, index: Field) -> T { + let (new_slice, elem) = self.slice.remove(index); + self.slice = new_slice; + elem +} +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 20, 30]); +let removed_elem = vector.remove(1); +assert(removed_elem == 20); +assert(vector.len() == 2); +``` + +### len + +Returns the number of elements in the vector. + +```rust +pub fn len(self) -> Field { + self.slice.len() +} +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/07_tuples.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/07_tuples.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/language_concepts/data_types/07_tuples.md rename to docs/versioned_docs/version-v0.19.3/language_concepts/data_types/07_tuples.md diff --git a/docs/docs/language_concepts/data_types/08_structs.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/08_structs.md similarity index 100% rename from docs/docs/language_concepts/data_types/08_structs.md rename to docs/versioned_docs/version-v0.19.3/language_concepts/data_types/08_structs.md diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/09_references.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/09_references.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/language_concepts/data_types/09_references.md rename to docs/versioned_docs/version-v0.19.3/language_concepts/data_types/09_references.md diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/10_function_types.md b/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/10_function_types.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/language_concepts/data_types/10_function_types.md rename to docs/versioned_docs/version-v0.19.3/language_concepts/data_types/10_function_types.md diff --git a/docs/versioned_docs/version-v0.19.3/migration_notes.md b/docs/versioned_docs/version-v0.19.3/migration_notes.md new file mode 100644 index 0000000000..0d7e0af0ef --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/migration_notes.md @@ -0,0 +1,91 @@ +--- +title: Migration notes +description: Read about migration notes from previous versions, which could solve problems while updating +keywords: [Noir, notes, migration, updating, upgrading] +--- + +Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. + +## ≥0.19 + +### Enforcing `compiler_version` + +From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. + +To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. + +## ≥0.14 + +The index of the [for loops](./language_concepts/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: + +```rust +for i in 0..10 { + let i = i as Field; +} +``` + +## ≥v0.11.0 and Nargo backend + +From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: + +### `backend encountered an error` + +This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. + +To fix the issue: + +1. Uninstall the existing backend + +```bash +nargo backend uninstall acvm-backend-barretenberg +``` + +You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. + +2. Reinstall a compatible version of the proving backend. + +If you are using the default barretenberg backend, simply run: + +``` +nargo prove +``` + +with you Noir program. + +This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. + +### `backend encountered an error: illegal instruction` + +On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. + +To fix the issue: + +1. Uninstall the existing backend + +```bash +nargo backend uninstall acvm-backend-barretenberg +``` + +You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. + +2. Reinstall a compatible version of the proving backend. + +If you are using the default barretenberg backend, simply run: + +``` +nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz +``` + +This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. + +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. + +Then run: + +``` +DESIRED_BINARY_VERSION=0.8.1 nargo info +``` + +This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. + +0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/crates_and_packages.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/modules_packages_crates/crates_and_packages.md rename to docs/versioned_docs/version-v0.19.3/modules_packages_crates/crates_and_packages.md diff --git a/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md new file mode 100644 index 0000000000..75f95aaa30 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md @@ -0,0 +1,123 @@ +--- +title: Dependencies +description: + Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub + and use them easily in your project. +keywords: [Nargo, dependencies, GitHub, package management, versioning] +--- + +Nargo allows you to upload packages to GitHub and use them as dependencies. + +## Specifying a dependency + +Specifying a dependency requires a tag to a specific commit and the git url to the url containing +the package. + +Currently, there are no requirements on the tag contents. If requirements are added, it would follow +semver 2.0 guidelines. + +> Note: Without a `tag` , there would be no versioning and dependencies would change each time you +> compile your project. + +For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: + +```toml +# Nargo.toml + +[dependencies] +ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} +``` + +If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: + +```toml +# Nargo.toml + +[dependencies] +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/src/contracts/easy_private_token_contract"} +``` + +## Specifying a local dependency + +You can also specify dependencies that are local to your machine. + +For example, this file structure has a library and binary crate + +```tree +├── binary_crate +│   ├── Nargo.toml +│   └── src +│   └── main.nr +└── liba + ├── Nargo.toml + └── src + └── lib.nr +``` + +Inside of the binary crate, you can specify: + +```toml +# Nargo.toml + +[dependencies] +libA = { path = "../liba" } +``` + +## Importing dependencies + +You can import a dependency to a Noir file using the following syntax. For example, to import the +ecrecover-noir library and local liba referenced above: + +```rust +use dep::ecrecover; +use dep::libA; +``` + +You can also import only the specific parts of dependency that you want to use, like so: + +```rust +use dep::std::hash::sha256; +use dep::std::scalar_mul::fixed_base_embedded_curve; +``` + +Lastly, as demonstrated in the +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +can import multiple items in the same line by enclosing them in curly braces: + +```rust +use dep::std::ec::tecurve::affine::{Curve, Point}; +``` + +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. + +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +## Dependencies of Dependencies + +Note that when you import a dependency, you also get access to all of the dependencies of that package. + +For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: + +```rust +use dep::phy_vector; + +fn main(x : Field, y : pub Field) { + //... + let f = phy_vector::fraction::toFraction(true, 2, 1); + //... +} +``` + +## Available Libraries + +Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). + +Some libraries that are available today include: + +- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library +- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) +- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers +- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address +- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees +- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir +- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/docs/versioned_docs/version-v0.10.5/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/modules.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/modules_packages_crates/modules.md rename to docs/versioned_docs/version-v0.19.3/modules_packages_crates/modules.md diff --git a/docs/docs/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md similarity index 100% rename from docs/docs/modules_packages_crates/workspaces.md rename to docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md diff --git a/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md b/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md new file mode 100644 index 0000000000..65e2bdb44e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md @@ -0,0 +1,250 @@ +--- +title: Commands +description: + Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, + generate Solidity verifier smart contract and compile into JSON file containing ACIR + representation and ABI of circuit. +keywords: + [ + Nargo, + Noir CLI, + Noir Prover, + Noir Verifier, + generate Solidity verifier, + compile JSON file, + ACIR representation, + ABI of circuit, + TypeScript, + ] +--- + +## General options + +| Option | Description | +| -------------------- | -------------------------------------------------- | +| `--show-ssa` | Emit debug information for the intermediate SSA IR | +| `--deny-warnings` | Quit execution when warnings are emitted | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo help [subcommand]` + +Prints the list of available commands or specific information of a subcommand. + +_Arguments_ + +| Argument | Description | +| -------------- | -------------------------------------------- | +| `` | The subcommand whose help message to display | + +## `nargo backend` + +Installs and selects custom backends used to generate and verify proofs. + +### Commands + +| Command | Description | +| ----------- | --------------------------------------------------------- | +| `current` | Prints the name of the currently active backend | +| `ls` | Prints the list of currently installed backends | +| `use` | Select the backend to use | +| `install` | Install a new backend from a URL | +| `uninstall` | Uninstalls a backend | +| `help` | Print this message or the help of the given subcommand(s) | + +### Options + +| Option | Description | +| ------------ | ----------- | +| `-h, --help` | Print help | + +## `nargo check` + +Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output +values of the Noir program respectively. + +### Options + +| Option | Description | +| --------------------- | ------------------------------------- | +| `--package ` | The name of the package to check | +| `--workspace` | Check all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +### `nargo codegen-verifier` + +Generate a Solidity verifier smart contract for the program. + +### Options + +| Option | Description | +| --------------------- | ------------------------------------- | +| `--package ` | The name of the package to codegen | +| `--workspace` | Codegen all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo compile` + +Compile the program into a JSON build artifact file containing the ACIR representation and the ABI +of the circuit. This build artifact can then be used to generate and verify proofs. + +You can also use "build" as an alias for compile (e.g. `nargo build`). + +### Options + +| Option | Description | +| --------------------- | ------------------------------------------------------------ | +| `--include-keys` | Include Proving and Verification keys in the build artifacts | +| `--package ` | The name of the package to compile | +| `--workspace` | Compile all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo new ` + +Creates a new Noir project in a new folder. + +**Arguments** + +| Argument | Description | +| -------- | -------------------------------- | +| `` | The path to save the new project | + +### Options + +| Option | Description | +| --------------- | ----------------------------------------------------- | +| `--name ` | Name of the package [default: package directory name] | +| `--lib` | Use a library template | +| `--bin` | Use a binary template [default] | +| `--contract` | Use a contract template | +| `-h, --help` | Print help | + +## `nargo init` + +Creates a new Noir project in the current directory. + +### Options + +| Option | Description | +| --------------- | ----------------------------------------------------- | +| `--name ` | Name of the package [default: current directory name] | +| `--lib` | Use a library template | +| `--bin` | Use a binary template [default] | +| `--contract` | Use a contract template | +| `-h, --help` | Print help | + +## `nargo execute [WITNESS_NAME]` + +Runs the Noir program and prints its return value. + +**Arguments** + +| Argument | Description | +| ---------------- | ----------------------------------------- | +| `[WITNESS_NAME]` | Write the execution witness to named file | + +### Options + +| Option | Description | +| --------------------------------- | ------------------------------------------------------------------------------------ | +| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | +| `--package ` | The name of the package to execute | +| `--workspace` | Execute all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +_Usage_ + +The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which +must be filled in. + +To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A +`.tr` file will then be saved in the `./target` folder. + +## `nargo prove` + +Creates a proof for the program. + +### Options + +| Option | Description | +| ------------------------------------- | ---------------------------------------------------------------------------------------- | +| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | +| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | +| `--verify` | Verify proof after proving | +| `--package ` | The name of the package to prove | +| `--workspace` | Prove all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo verify` + +Given a proof and a program, verify whether the proof is valid. + +### Options + +| Option | Description | +| ------------------------------------- | ---------------------------------------------------------------------------------------- | +| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | +| `--package ` | The name of the package to verify | +| `--workspace` | Verify all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo test [TEST_NAME]` + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. + +Takes an optional `--exact` flag which allows you to select tests based on an exact name. + +See an example on the [testing page](./testing). + +### Options + +| Option | Description | +| --------------------- | -------------------------------------- | +| `--show-output` | Display output of `println` statements | +| `--exact` | Only run tests that match exactly | +| `--package ` | The name of the package to test | +| `--workspace` | Test all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo info` + +Prints a table containing the information of the package. + +Currently the table provide + +1. The number of ACIR opcodes +2. The final number gates in the circuit used by a backend + +If the file contains a contract the table will provide the +above information about each function of the contract. + +## `nargo lsp` + +Start a long-running Language Server process that communicates over stdin/stdout. +Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). + +## `nargo fmt` + +Automatically formats your Noir source code based on the default formatting settings. diff --git a/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md new file mode 100644 index 0000000000..da767274ef --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/nargo/02_testing.md @@ -0,0 +1,61 @@ +--- +title: Testing in Noir +description: Learn how to use Nargo to test your Noir program in a quick and easy way +keywords: [Nargo, testing, Noir, compile, test] +--- + +You can test your Noir programs using Noir circuits. + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. + +For example if you have a program like: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test] +fn test_add() { + assert(add(2,2) == 4); + assert(add(0,1) == 1); + assert(add(1,0) == 1); +} +``` + +Running `nargo test` will test that the `test_add` function can be executed while satisfying the all +the contraints which allows you to test that add returns the expected values. Test functions can't +have any arguments currently. + +### Test fail + +You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test(should_fail)] +fn test_add() { + assert(add(2,2) == 5); +} +``` + +You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: + +```rust +fn main(african_swallow_avg_speed : Field) { + assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); +} + +#[test] +fn test_king_arthur() { + main(65); +} + +#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] +fn test_bridgekeeper() { + main(32); +} + +``` diff --git a/docs/versioned_docs/version-v0.10.5/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.19.3/nargo/03_solidity_verifier.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/nargo/03_solidity_verifier.md rename to docs/versioned_docs/version-v0.19.3/nargo/03_solidity_verifier.md diff --git a/docs/versioned_docs/version-v0.19.3/nargo/04_language_server.md b/docs/versioned_docs/version-v0.19.3/nargo/04_language_server.md new file mode 100644 index 0000000000..48c01465f6 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/nargo/04_language_server.md @@ -0,0 +1,42 @@ +--- +title: Language Server +description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. +keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +--- + +This section helps you install and configure the Noir Language Server. + +The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. + +## Language Server + +The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. +As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! + +If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. + +## Language Client + +The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. + +Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). +> +> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. + +When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: + +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) + +You should also see your tests in the `testing` panel: + +![Testing panel](@site/static/img/codelens_testing_panel.png) + +### Configuration + +- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. +- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. +- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. +- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/getting_started/01_tiny_noir_app.md b/docs/versioned_docs/version-v0.19.3/noir_js/getting_started/01_tiny_noir_app.md new file mode 100644 index 0000000000..c51ed61de5 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/getting_started/01_tiny_noir_app.md @@ -0,0 +1,260 @@ +--- +title: End-to-end +description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment +keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] +--- + +NoirJS works both on the browser and on the server, and works for both ESM and CJS module systems. In this page, we will learn how can we write a simple test and a simple web app to verify the standard Noir example. + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Before we start + +:::note + +Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.18.x matches `noir_js@0.18.x`, etc. + +In this guide, we will be pinned to 0.17.0. + +::: + +Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). + +First of all, follow the the [Nargo guide](../../getting_started/00_nargo_installation.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: + +```bash +nargo compile +``` + +Your folder structure should look like: + +```tree +. +└── circuit + ├── Nargo.toml + ├── src + │ └── main.nr + └── target + └── circuit.json +``` + +## Starting a new project + +Go back to the previous folder and start a new project by running run `npm init`. You can configure your project or just leave the defaults, and see a `package.json` appear in your root folder. + +## Installing dependencies + +We'll need two `npm` packages. These packages will provide us the methods we need to run and verify proofs: + +```bash +npm i @noir-lang/backend_barretenberg@^0.17.0 @noir-lang/noir_js@^0.17.0 +``` + +To serve our page, we can use a build tool such as `vite`. Because we're gonna use some `wasm` files, we need to install a plugin as well. Run: + +```bash +npm i --save-dev vite rollup-plugin-copy +``` + +Since we're on the dependency world, we may as well define a nice starting script. Vite makes it easy. Just open `package.json`, find the block "scripts" and add this just below the line with `"test" : "echo......."`: + +```json + "start": "vite --open" +``` + +If you want do build a static website, you can also add some build and preview scripts: + +```json + "build": "vite build", + "preview": "vite preview" +``` + +## Vite plugins + +Vite is great, but support from `wasm` doesn't work out-of-the-box. We're gonna write a quick plugin and use another one. Just copy and paste this into a file named `vite.config.js`. You don't need to understand it, just trust me bro. + +```js +import { defineConfig } from 'vite'; +import copy from 'rollup-plugin-copy'; +import fs from 'fs'; +import path from 'path'; + +const wasmContentTypePlugin = { + name: 'wasm-content-type-plugin', + configureServer(server) { + server.middlewares.use(async (req, res, next) => { + if (req.url.endsWith('.wasm')) { + res.setHeader('Content-Type', 'application/wasm'); + const newPath = req.url.replace('deps', 'dist'); + const targetPath = path.join(__dirname, newPath); + const wasmContent = fs.readFileSync(targetPath); + return res.end(wasmContent); + } + next(); + }); + }, +}; + +export default defineConfig(({ command }) => { + if (command === 'serve') { + return { + plugins: [ + copy({ + targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], + copySync: true, + hook: 'buildStart', + }), + command === 'serve' ? wasmContentTypePlugin : [], + ], + }; + } + + return {}; +}); +``` + +## HTML + +Here's the simplest HTML with some terrible UI. Create a file called `index.html` and paste this: + +```html + + + + + + +

Very basic Noir app

+
+

Logs

+

Proof

+
+ + +``` + +## Some good old vanilla Javascript + +Create a new file `app.js`, which is where our javascript code will live. Let's start with this code inside: + +```js +document.addEventListener('DOMContentLoaded', async () => { + // here's where the magic happens +}); + +function display(container, msg) { + const c = document.getElementById(container); + const p = document.createElement('p'); + p.textContent = msg; + c.appendChild(p); +} +``` + +We can manipulate our website with this little function, so we can see our website working. + +## Adding Noir + +If you come from the previous page, your folder structure should look like this: + +```tree +├── app.js +├── circuit +│ ├── Nargo.toml +│ ├── src +│ │ └── main.nr +│ └── target +│ └── circuit.json +├── index.html +├── package.json +└── vite.config.js +``` + +You'll see other files and folders showing up (like `package-lock.json`, `yarn.lock`, `node_modules`) but you shouldn't have to care about those. + +## Importing our dependencies + +We're starting with the good stuff now. At the top of the new javascript file, import the packages: + +```ts +import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; +``` + +We also need to import the `circuit` JSON file we created. If you have the suggested folder structure, you can add this line: + +```ts +import circuit from './circuit/target/circuit.json'; +``` + +## Write code + +:::note + +We're gonna be adding code inside the `document.addEventListener...etc` block: + +```js +// forget stuff here +document.addEventListener('DOMContentLoaded', async () => { + // here's where the magic happens +}); +// forget stuff here +``` + +::: + +Our dependencies exported two classes: `BarretenbergBackend` and `Noir`. Let's `init` them and add some logs, just to flex: + +```ts +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit, backend); +``` + +## Proving + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +const input = { x: 1, y: 2 }; +display('logs', 'Generating proof... ⌛'); +const proof = await noir.generateFinalProof(input); +display('logs', 'Generating proof... ✅'); +display('results', proof.proof); +``` + +You're probably eager to see stuff happening, so go and run your app now! + +From your terminal, run `npm start` (or `yarn start`). If it doesn't open a browser for you, just visit `localhost:5173`. On a modern laptop, proof will generate in less than 100ms, and you'll see this: + +![Getting Started 0](@site/static/img/noir_getting_started_1.png) + +If you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human. + +In any case, this means your proof was generated! But you shouldn't trust me just yet. Add these lines to see it being verified: + +```js +display('logs', 'Verifying proof... ⌛'); +const verification = await noir.verifyFinalProof(proof); +if (verification) display('logs', 'Verifying proof... ✅'); +``` + +By saving, your app will refresh and here's our complete Tiny Noir App! + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Further Reading + +You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/next-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. + +You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/docs/docs/noir_js/noir_js.md b/docs/versioned_docs/version-v0.19.3/noir_js/noir_js.md similarity index 100% rename from docs/docs/noir_js/noir_js.md rename to docs/versioned_docs/version-v0.19.3/noir_js/noir_js.md diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/.nojekyll new file mode 100644 index 0000000000..e2ac6616ad --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 0000000000..5cbe9421b9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,185 @@ +# BarretenbergBackend + +## Implements + +- [`Backend`](../interfaces/Backend.md) + +## Constructors + +### new BarretenbergBackend(acirCircuit, options) + +```ts +new BarretenbergBackend(acirCircuit, options): BarretenbergBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergBackend`](BarretenbergBackend.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(witness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `witness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) + +#### Example + +```typescript +const intermediateProof = await backend.generateIntermediateProof(witness); +``` + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) + +#### Example + +```typescript +const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) + +#### Example + +```typescript +const isValidIntermediate = await backend.verifyIntermediateProof(proof); +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/index.md new file mode 100644 index 0000000000..3680ba3ca7 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/index.md @@ -0,0 +1,27 @@ +# Backend Barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | + +### Interfaces + +| Interface | Description | +| :------ | :------ | +| [Backend](interfaces/Backend.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/interfaces/Backend.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/interfaces/Backend.md new file mode 100644 index 0000000000..3eb9645c8d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/interfaces/Backend.md @@ -0,0 +1,132 @@ +# Backend + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates an intermediate proof (meant to be verified in another circuit) + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | +| `numOfPublicInputs` | `number` | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Retrieves the artifacts from a proof in the Field format + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies an intermediate proof + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 0000000000..266ade75d1 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,19 @@ +# BackendOptions + +```ts +type BackendOptions: object; +``` + +## Description + +An options object, currently only used to specify the number of threads to use. + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `threads` | `number` | **Description**

Number of threads | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md new file mode 100644 index 0000000000..34e0dd0420 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

ABI representation of the circuit | +| `bytecode` | `string` | **Description**

The bytecode of the circuit | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md new file mode 100644 index 0000000000..4aeff73d3e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md @@ -0,0 +1,20 @@ +# ProofData + +```ts +type ProofData: object; +``` + +## Description + +The representation of a proof + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | +| `publicInputs` | `Uint8Array`[] | **Description**

Public inputs of a proof | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 0000000000..04e662c845 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/.nojekyll b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/.nojekyll new file mode 100644 index 0000000000..e2ac6616ad --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/classes/Noir.md new file mode 100644 index 0000000000..a8a0bb451c --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/classes/Noir.md @@ -0,0 +1,131 @@ +# Noir + +## Constructors + +### new Noir(circuit, backend) + +```ts +new Noir(circuit, backend?): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `backend`? | `Backend` | + +#### Returns + +[`Noir`](Noir.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the underlying backend instance. + +#### Example + +```typescript +await noir.destroy(); +``` + +*** + +### execute() + +```ts +execute(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | `InputMap` | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Allows to execute a circuit to get its witness and return value. + +#### Example + +```typescript +async execute(inputs) +``` + +*** + +### generateFinalProof() + +```ts +generateFinalProof(inputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | `InputMap` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a witness and a proof given an object as input. + +#### Example + +```typescript +async generateFinalproof(input) +``` + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Instantiates the verification key and verifies a proof. + +#### Example + +```typescript +async verifyFinalProof(proof) +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/and.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/and.md new file mode 100644 index 0000000000..c783283e39 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/blake2s256.md new file mode 100644 index 0000000000..7882d0da8d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 0000000000..0ba5783f0d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,29 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. +Verifies a ECDSA signature over the secp256k1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 0000000000..0b20ff6895 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/keccak256.md new file mode 100644 index 0000000000..d10f155ce8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/sha256.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/sha256.md new file mode 100644 index 0000000000..6ba4ecac02 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/xor.md new file mode 100644 index 0000000000..8d762b895d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/index.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/index.md new file mode 100644 index 0000000000..58902c17b9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/index.md @@ -0,0 +1,36 @@ +# Noir JS + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | +| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | +| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | +| [WitnessMap](type-aliases/WitnessMap.md) | - | + +### Functions + +| Function | Description | +| :------ | :------ | +| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | +| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | +| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | +| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | +| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | +| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | +| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md new file mode 100644 index 0000000000..34e0dd0420 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

ABI representation of the circuit | +| `bytecode` | `string` | **Description**

The bytecode of the circuit | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 0000000000..812b8b1648 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# ForeignCallHandler + +```ts +type ForeignCallHandler: (name, inputs) => Promise; +``` + +A callback which performs an foreign call and returns the response. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | The identifier for the type of foreign call being performed. | +| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | + +## Returns + +`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> + +outputs - An array of hex encoded outputs containing the results of the foreign call. + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 0000000000..dd95809186 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# ForeignCallInput + +```ts +type ForeignCallInput: string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 0000000000..b71fb78a94 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# ForeignCallOutput + +```ts +type ForeignCallOutput: string | string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ProofData.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ProofData.md new file mode 100644 index 0000000000..4aeff73d3e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/ProofData.md @@ -0,0 +1,20 @@ +# ProofData + +```ts +type ProofData: object; +``` + +## Description + +The representation of a proof + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | +| `publicInputs` | `Uint8Array`[] | **Description**

Public inputs of a proof | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 0000000000..258c46f9d0 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/typedoc-sidebar.cjs new file mode 100644 index 0000000000..c18318850d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/noir_js/reference/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"noir_js/reference/noir_js/functions/and","label":"and"},{"type":"doc","id":"noir_js/reference/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md new file mode 100644 index 0000000000..1dfabfe8f2 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md @@ -0,0 +1,46 @@ +--- +title: Black Box Functions +description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. +keywords: [noir, black box functions] +--- + +Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. + +:::warning + +It is likely that not all backends will support a particular black box function. + +::: + +Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. + +Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: + +```rust +#[foreign(sha256)] +fn sha256(_input : [u8; N]) -> [u8; 32] {} +``` + +## Function list + +Here is a list of the current black box functions that are supported by UltraPlonk: + +- AES +- [SHA256](./cryptographic_primitives/hashes#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr) +- [Blake2s](./cryptographic_primitives/hashes#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) +- [Compute merkle root](./merkle_trees#compute_merkle_root) +- AND +- XOR +- RANGE +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) + +Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. + +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives.md rename to docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives.md diff --git a/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/00_hashes.mdx new file mode 100644 index 0000000000..7674519668 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/00_hashes.mdx @@ -0,0 +1,167 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s, pedersen, mimc_bn254 and mimc +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## sha256 + +Given an array of bytes, returns the resulting sha256 hash. + +```rust +fn sha256(_input : [u8]) -> [u8; 32] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::sha256(x); +} +``` + + + +## blake2s + +Given an array of bytes, returns an array with the Blake2 hash + +```rust +fn blake2s(_input : [u8]) -> [u8; 32] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake2s(x); +} +``` + + + +## pedersen_hash + +Given an array of Fields, returns the Pedersen hash. + +```rust +fn pedersen_hash(_input : [Field]) -> Field +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::pedersen_hash(x); +} +``` + + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust +fn pedersen_commitment(_input : [Field]) -> [Field; 2] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let commitment = std::hash::pedersen_commitment(x); +} +``` + + + +## keccak256 + +Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes +(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes +of the input. + +```rust +fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let message_size = 4; + let hash = std::hash::keccak256(x, message_size); +} +``` + + + +## poseidon + +Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify +how many inputs are there to your Poseidon function. + +```rust +// example for hash_1, hash_2 accepts an array of length 2, etc +fn hash_1(input: [Field; 1]) -> Field +``` + +example: + +```rust +fn main() +{ + let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); + assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); +} +``` + +## mimc_bn254 and mimc + +`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by +providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if +you're willing to input your own constants: + +```rust +fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field +``` + +otherwise, use the `mimc_bn254` method: + +```rust +fn mimc_bn254(array: [Field; N]) -> Field +``` + +example: + +```rust + +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::mimc::mimc_bn254(x); +} +``` + +## hash_to_field + +```rust +fn hash_to_field(_input : [Field; N]) -> Field {} +``` + +Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return +a value which can be represented as a `Field`. + + diff --git a/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/01_scalar.mdx new file mode 100644 index 0000000000..c7eed820a8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/01_scalar.mdx @@ -0,0 +1,27 @@ +--- +title: Scalar multiplication +description: See how you can perform scalar multiplications over a fixed base in Noir +keywords: [cryptographic primitives, Noir project, scalar multiplication] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## scalar_mul::fixed_base_embedded_curve + +Performs scalar multiplication over the embedded curve whose coordinates are defined by the +configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. + +```rust +fn fixed_base_embedded_curve(_input : Field) -> [Field; 2] +``` + +example + +```rust +fn main(x : Field) { + let scal = std::scalar_mul::fixed_base_embedded_curve(x); + std::println(scal); +} +``` + + diff --git a/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/02_schnorr.mdx new file mode 100644 index 0000000000..c184ce2812 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/02_schnorr.mdx @@ -0,0 +1,37 @@ +--- +title: Schnorr Signatures +description: Learn how you can verify Schnorr signatures using Noir +keywords: [cryptographic primitives, Noir project, schnorr, signatures] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## schnorr::verify_signature + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). + +```rust +fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool +``` + +where `_signature` can be generated like so using the npm package +[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) + +```js +const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); +const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); + +... + +const barretenberg = await BarretenbergWasm.new(); +const schnorr = new Schnorr(barretenberg); +const pubKey = schnorr.computePublicKey(privateKey); +const message = ... +const signature = Array.from( + schnorr.constructSignature(hash, privateKey).toBuffer() +); + +... +``` + + diff --git a/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx new file mode 100644 index 0000000000..72bce98482 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx @@ -0,0 +1,45 @@ +--- +title: ECDSA Signature Verification +description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves +keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. + +## ecdsa_secp256k1::verify_signature + +Verifier for ECDSA Secp256k1 signatures + +```rust +fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool +``` + +example: + +```rust +fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { + let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} +``` + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures + +```rust +fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool +``` + +example: + +```rust +fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { + let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} +``` + + diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/04_ec_primitives.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/04_ec_primitives.md rename to docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/04_ec_primitives.md diff --git a/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/05_eddsa.mdx new file mode 100644 index 0000000000..9a5beb55ee --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/standard_library/cryptographic_primitives/05_eddsa.mdx @@ -0,0 +1,17 @@ +--- +title: EdDSA Verification +description: Learn about the cryptographic primitives regarding EdDSA +keywords: [cryptographic primitives, Noir project, eddsa, signatures] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## eddsa::eddsa_poseidon_verify + +Verifier for EdDSA signatures + +```rust +fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool +``` + + diff --git a/docs/versioned_docs/version-v0.10.5/standard_library/logging.md b/docs/versioned_docs/version-v0.19.3/standard_library/logging.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/standard_library/logging.md rename to docs/versioned_docs/version-v0.19.3/standard_library/logging.md diff --git a/docs/versioned_docs/version-v0.19.3/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.19.3/standard_library/merkle_trees.md new file mode 100644 index 0000000000..dc383a1426 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/standard_library/merkle_trees.md @@ -0,0 +1,58 @@ +--- +title: Merkle Trees +description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. +keywords: + [ + Merkle trees in Noir, + Noir programming language, + check membership, + computing root from leaf, + Noir Merkle tree implementation, + Merkle tree tutorial, + Merkle tree code examples, + Noir libraries, + pedersen hash., + ] +--- + +## compute_merkle_root + +Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen_hash). + +```rust +fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field +``` + +example: + +```rust +/** + // these values are for this example only + index = "0" + priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" + secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" + note_hash_path = [ + "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", + "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", + "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" + ] + */ +fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { + + let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); + let pubkey_x = pubkey[0]; + let pubkey_y = pubkey[1]; + let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); + + let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); + std::println(root); +} +``` + +To check merkle tree membership: + +1. Include a merkle root as a program input. +2. Compute the merkle root of a given leaf, index and hash path. +3. Assert the merkle roots are equal. + +For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/docs/versioned_docs/version-v0.19.3/standard_library/options.md b/docs/versioned_docs/version-v0.19.3/standard_library/options.md new file mode 100644 index 0000000000..3d3139fb98 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/standard_library/options.md @@ -0,0 +1,99 @@ +--- +title: Option Type +--- + +The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. + +```rust +struct Option { + None, + Some(T), +} +``` + +You can import the Option type into your Noir program like so: + +```rust +use dep::std::option::Option; + +fn main() { + let none = Option::none(); + let some = Option::some(3); +} +``` + +See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. + +## Methods + +### none + +Constructs a none value. + +### some + +Constructs a some wrapper around a given value. + +### is_none + +Returns true if the Option is None. + +### is_some + +Returns true of the Option is Some. + +### unwrap + +Asserts `self.is_some()` and returns the wrapped value. + +### unwrap_unchecked + +Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. + +### unwrap_or + +Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. + +### unwrap_or_else + +Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. + +### map + +If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. + +### map_or + +If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. + +### map_or_else + +If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. + +### and + +Returns None if self is None. Otherwise, this returns `other`. + +### and_then + +If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. + +### or + +If self is Some, return self. Otherwise, return `other`. + +### or_else + +If self is Some, return self. Otherwise, return `default()`. + +### xor + +If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. + +### filter + +Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. + +### flatten + +Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md b/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md new file mode 100644 index 0000000000..ff4c63acaa --- /dev/null +++ b/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md @@ -0,0 +1,96 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] +--- + +Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. + +The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. + +```rust +#[foreign(verify_proof)] +fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} +``` + +:::info + +This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. + +::: + +## Aggregation Object + +The purpose of the input aggregation object is a little less clear though (and the output aggregation object that is returned from the `std::verify_proof` method). Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points (thus completing the recursive verification). + +So for example in this circuit: + +```rust +use dep::std; + +fn main( + verification_key : [Field; 114], + proof : [Field; 94], + public_inputs : [Field; 1], + key_hash : Field, + input_aggregation_object : [Field; 16], + proof_b : [Field; 94], +) -> pub [Field; 16] { + let output_aggregation_object_a = std::verify_proof( + verification_key, + proof, + public_inputs, + key_hash, + input_aggregation_object + ); + + let output_aggregation_object = std::verify_proof( + verification_key, + proof_b, + public_inputs, + key_hash, + output_aggregation_object_a + ); + + let mut output = [0; 16]; + for i in 0..16 { + output[i] = output_aggregation_object[i]; + } + output +} +``` + +In this example we have a circuit, that generates proofs A and B, that is being verified in circuit C. Assuming that the proof being passed in is not already a recursive proof, the `input_aggregation_object` will be all zeros. It will then generate an `output_aggregation_object`. This blob of data then becomes the `input_aggregation_object` of the next recursive aggregation we wish to compute. We can see here as the same public inputs, verification key, and key hash are used that we are verifying two proofs generated from the same circuit in this single circuit. `std::verify_proof` returns a `[Field]` because the size of an aggregation object is proof system dependent--in barretenberg, aggregation objects are two G1 points, while in Halo2, the aggregation object is a list of G1 points that is log the circuit size. So for the final step we convert the slice into an array of size 16 because we are generating proofs using UltraPlonk. + +## Parameters + +### `verification_key` + +The verification key for the zk program that is being verified. + +### `proof` + +The proof for the zk program that is being verified. + +### `public_inputs` + +These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. + +### `key_hash` + +A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. + +### `input_aggregation_object` + +An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. + +## Return value + +### `output_aggregation_object` + +This is the result of a recursive aggregation and is what will be fed into the next verifier. +The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. + +## Example + +You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/zeroed.md b/docs/versioned_docs/version-v0.19.3/standard_library/zeroed.md similarity index 100% rename from docs/versioned_docs/version-v0.6.0/standard_library/zeroed.md rename to docs/versioned_docs/version-v0.19.3/standard_library/zeroed.md diff --git a/docs/versioned_docs/version-v0.19.4/examples/merkle-proof.mdx b/docs/versioned_docs/version-v0.19.4/examples/merkle-proof.mdx new file mode 100644 index 0000000000..832fb4bb55 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/examples/merkle-proof.mdx @@ -0,0 +1,48 @@ +--- +title: Merkle Proof Membership +description: + Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a + merkle tree with a specified root, at a given index. +keywords: + [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +--- + +Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is +in a merkle tree. + +```rust +use dep::std; + +fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { + let leaf = std::hash::hash_to_field(message); + let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); + assert(merkle_root == root); +} + +``` + +The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen +by the backend. The only requirement is that this hash function can heuristically be used as a +random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` +instead. + +```rust +let leaf = std::hash::hash_to_field(message); +``` + +The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. + +```rust +let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); +assert (merkle_root == root); +``` + +> **Note:** It is possible to re-implement the merkle tree implementation without standard library. +> However, for most usecases, it is enough. In general, the standard library will always opt to be +> as conservative as possible, while striking a balance with efficiency. + +An example, the merkle membership proof, only requires a hash function that has collision +resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient +than the even more conservative sha256. + +[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md new file mode 100644 index 0000000000..349756d60c --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/getting_started/00_nargo_installation.md @@ -0,0 +1,249 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, + verifying and more). Learn how to install and use Nargo for your projects with this comprehensive + guide. +keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] +--- + +`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, +verifying and more). + +Alternatively, the interactions can also be performed in [NoirJS](../noir_js/noir_js.md). + +### UltraPlonk + +Nargo versions \<0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk +version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. + +## Installation + +There are four approaches for installing Nargo: + +- [Option 1: Noirup](#option-1-noirup) +- [Option 2: Binaries](#option-2-binaries) +- [Option 3: Compile from Source](#option-3-compile-from-source) +- [Option 4: WSL for Windows](#option-4-wsl-for-windows) + +Optionally you can also install [Noir VS Code extension] for syntax highlighting. + +### Option 1: Noirup + +If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a +terminal and run: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done, you should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. + +#### GitHub Actions + +You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as +installing `noirup` and running tests in your GitHub Action `yml` file. + +See the +[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in +this repo containing hash functions in Noir for an example. + +#### Nightly versions + +To install the nightly version of Noir (updated daily) run: + +```bash +noirup -n +``` + +### Option 2: Binaries + +See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous +platform specific binaries. + +#### Step 1 + +Paste and run the following in the terminal to extract and install the binary: + +> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend +> `sudo` and re-run it. + +##### macOS (Apple Silicon) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ +echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ +source ~/.zshrc +``` + +##### macOS (Intel) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ +echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ +source ~/.zshrc +``` + +##### Linux (Bash) + +```bash +mkdir -p $HOME/.nargo/bin && \ +curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ +tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ +echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ +source ~/.bashrc +``` + +#### Step 2 + +Check if the installation was successful by running `nargo --help`. + +> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from +> Finder. Close the new terminal popped up and `nargo` should now be accessible. + +For a successful installation, you should see something similar to the following after running the +command: + +```sh +$ nargo --help + +Noir's package manager + +Usage: nargo + +Commands: + check Checks the constraint system for errors + codegen-verifier Generates a Solidity verifier smart contract for the program + compile Compile the program and its secret execution trace into ACIR format + new Create a new binary project + execute Executes a circuit to calculate its return value + prove Create proof for this program. The proof is returned as a hex encoded string + verify Given a proof and a program, verify whether the proof is valid + test Run the tests for this program + gates Counts the occurrences of different gates in circuit + help Print this message or the help of the given subcommand(s) +``` + +### Option 3: Compile from Source + +Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. It helps mitigating ssues commonly associated with dependency management, such as conflicts between required package versions for different projects (often referred to as "dependency hell"). + +Combined with direnv, which automatically sets or unsets environment variables based on the directory, it further simplifies the development process by seamlessly integrating with the developer's shell, facilitating an efficient and reliable workflow for managing and deploying Noir projects with multiple dependencies. + +#### Setting up your environment + +For the best experience, please follow these instructions to setup your environment: + +1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. +2. Create the file `~/.config/nix/nix.conf` with the contents: + +```ini +experimental-features = nix-command +extra-experimental-features = flakes +``` + +3. Install direnv into your Nix profile by running: + +```sh +nix profile install nixpkgs#direnv +``` + +4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). + 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. +5. Restart your shell. + +#### Shell & editor experience + +Now that your environment is set up, you can get to work on the project. + +1. Clone the repository, such as: + +```sh +git clone git@github.com:noir-lang/noir +``` + +> Replacing `noir` with whichever repository you want to work on. + +2. Navigate to the directory: + +```sh +cd noir +``` + +> Replacing `noir` with whichever repository you cloned. + +3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: + +```sh +direnv allow +``` + +4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. + +5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): + +```sh +code . +``` + +6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. + +#### Building and testing + +Assuming you are using `direnv` to populate your environment, building and testing the project can be done +with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `rust-toolchain.toml`, which is 1.71.1 at the time of this writing. + +If you want to build the entire project in an isolated sandbox, you can use Nix commands: + +1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. +2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. + +#### Without `direnv` + +If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. + +Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! + +### Option 4: WSL (for Windows) + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed nativerly. However, it is available by using Windows Subsystem for Linux (WSL). + +Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. + +step 2: Follow the [Noirup instructions](#option-1-noirup). + +## Uninstalling Nargo + +### Noirup + +If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` + +### Nix + +If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. + +```bash +rm ~/.nix-profile/bin/nargo +``` + +[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir diff --git a/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md new file mode 100644 index 0000000000..8b4416beba --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md @@ -0,0 +1,147 @@ +--- +title: Create A Project +description: + Learn how to create and verify your first Noir program using Nargo, a programming language for + zero-knowledge proofs. +keywords: + [ + Nargo, + Noir, + zero-knowledge proofs, + programming language, + create Noir program, + verify Noir program, + step-by-step guide, + ] +--- + +Now that we have installed Nargo, it is time to make our first hello world program! + +## Create a Project Directory + +Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home +directory to house our Noir programs. + +For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by +running: + +```sh +mkdir ~/projects +cd ~/projects +``` + +For Windows CMD, run: + +```sh +> mkdir "%USERPROFILE%\projects" +> cd /d "%USERPROFILE%\projects" +``` + +## Create Our First Nargo Project + +Now that we are in the projects directory, create a new Nargo project by running: + +```sh +nargo new hello_world +``` + +> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for +> demonstration. +> +> In production, the common practice is to name the project folder as `circuits` for better +> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, +> `test`). + +A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and +_Nargo.toml_ that contains the source code and environmental options of your Noir program +respectively. + +### Intro to Noir Syntax + +Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +The first line of the program specifies the program's inputs: + +```rust +x : Field, y : pub Field +``` + +Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the +keyword `pub` (e.g. `y`). To learn more about private and public values, check the +[Data Types](../language_concepts/data_types) section. + +The next line of the program specifies its body: + +```rust +assert(x != y); +``` + +The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. + +For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. + +## Build In/Output Files + +Change directory into _hello_world_ and build in/output files for your Noir program by running: + +```sh +cd hello_world +nargo check +``` + +Two additional files would be generated in your project directory: + +_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. + +## Prove Our Noir Program + +Now that the project is set up, we can create a proof of correct execution on our Noir program. + +Fill in input values for execution in the _Prover.toml_ file. For example: + +```toml +x = "1" +y = "2" +``` + +Prove the valid execution of your Noir program: + +```sh +nargo prove +``` + +A new folder _proofs_ would then be generated in your project directory, containing the proof file +`.proof`, where the project name is defined in Nargo.toml. + +The _Verifier.toml_ file would also be updated with the public values computed from program +execution (in this case the value of `y`): + +```toml +y = "0x0000000000000000000000000000000000000000000000000000000000000002" +``` + +> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. + +## Verify Our Noir Program + +Once a proof is generated, we can verify correct execution of our Noir program by verifying the +proof file. + +Verify your proof by running: + +```sh +nargo verify +``` + +The verification will complete in silence if it is successful. If it fails, it will log the +corresponding error instead. + +Congratulations, you have now created and verified a proof for your very first Noir program! + +In the [next section](breakdown), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md new file mode 100644 index 0000000000..9a17f5d636 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md @@ -0,0 +1,198 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML + files, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] +--- + +This section breaks down our hello world program in section _1.2_. We elaborate on the project +structure and what the `prove` and `verify` commands did in the previous section. + +## Anatomy of a Nargo Project + +Upon creating a new project with `nargo new` and building the in/output files with `nargo check` +commands, you would get a minimal Nargo project of the following structure: + + - src + - Prover.toml + - Verifier.toml + - Nargo.toml + +The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ +file will be generated within it. + +### Prover.toml + +_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. + +### Verifier.toml + +_Verifier.toml_ contains public in/output values computed when executing the Noir program. + +### Nargo.toml + +_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. + +Example Nargo.toml: + +```toml +[package] +name = "noirstarter" +type = "bin" +authors = ["Alice"] +compiler_version = "0.9.0" +description = "Getting started with Noir" +entry = "circuit/main.nr" +license = "MIT" + +[dependencies] +ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} +``` + +Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +#### Package section + +The package section requires a number of fields including: + +- `name` (**required**) - the name of the package +- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract +- `authors` (optional) - authors of the project +- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) +- `description` (optional) +- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) +- `backend` (optional) +- `license` (optional) + +#### Dependencies section + +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. + +`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or +verifier contract respectively. + +### main.nr + +The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. + +In our sample program, _main.nr_ looks like this: + +```rust +fn main(x : Field, y : Field) { + assert(x != y); +} +``` + +The parameters `x` and `y` can be seen as the API for the program and must be supplied by the +prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when +verifying the proof. + +The prover supplies the values for `x` and `y` in the _Prover.toml_ file. + +As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is +constrained by the proof of the execution of said program (i.e. if the condition was not met, the +verifier would reject the proof as an invalid proof). + +### Prover.toml + +The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and +public). + +In our hello world program the _Prover.toml_ file looks like this: + +```toml +x = "1" +y = "2" +``` + +When the command `nargo prove` is executed, two processes happen: + +1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` + is not equal. This not equal constraint is due to the line `assert(x != y)`. + +2. Noir creates and stores the proof of this statement in the _proofs_ directory in a file called your-project.proof. So if your project is named "private_voting" (defined in the project Nargo.toml), the proof will be saved at `./proofs/private_voting.proof`. Opening this file will display the proof in hex format. + +#### Arrays of Structs + +The following code shows how to pass an array of structs to a Noir program to generate a proof. + +```rust +// main.nr +struct Foo { + bar: Field, + baz: Field, +} + +fn main(foos: [Foo; 3]) -> pub Field { + foos[2].bar + foos[2].baz +} +``` + +Prover.toml: + +```toml +[[foos]] # foos[0] +bar = 0 +baz = 0 + +[[foos]] # foos[1] +bar = 0 +baz = 0 + +[[foos]] # foos[2] +bar = 1 +baz = 2 +``` + +#### Custom toml files + +You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. + +This command looks for proof inputs in the default **Prover.toml** and generates the proof and saves it at `./proofs/.proof`: + +```bash +nargo prove +``` + +This command looks for proof inputs in the custom **OtherProver.toml** and generates proof and saves it at `./proofs/.proof`: + +```bash +nargo prove -p OtherProver +``` + +## Verifying a Proof + +When the command `nargo verify` is executed, two processes happen: + +1. Noir checks in the _proofs_ directory for a proof file with the project name (eg. test_project.proof) + +2. If that file is found, the proof's validity is checked + +> **Note:** The validity of the proof is linked to the current Noir program; if the program is +> changed and the verifier verifies the proof, it will fail because the proof is not valid for the +> _modified_ Noir program. + +In production, the prover and the verifier are usually two separate entities. A prover would +retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the +verifier. The verifier would then retrieve the public inputs from usually external sources and +verifies the validity of the proof against it. + +Take a private asset transfer as an example: + +A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and +public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof +and submit it to the verifier smart contract. + +The verifier contract would then draw the user's encrypted balance directly from the blockchain and +verify the proof submitted against it. If the verification passes, additional functions in the +verifier contract could trigger (e.g. approve the asset transfer). + +Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/docs/versioned_docs/version-v0.19.4/index.md b/docs/versioned_docs/version-v0.19.4/index.md new file mode 100644 index 0000000000..4e2f404389 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/index.md @@ -0,0 +1,100 @@ +--- +title: Introducing Noir +description: + Learn about the public alpha release of Noir, a domain specific language heavily influenced by + Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a + rank-1 constraint system. +keywords: + [ + Noir, + Domain Specific Language, + Rust, + Intermediate Language, + Arithmetic Circuit, + Rank-1 Constraint System, + Ethereum Developers, + Protocol Developers, + Blockchain Developers, + Proving System, + Smart Contract Language, + ] +slug: / +--- + +## What is Noir? + +Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. + +It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. + +## Who is Noir for? + +Noir can be used for a variety of purposes. + +### Solidity Developers + +Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will +be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +a verifier contract. + +### Protocol Developers + +As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for +your stack, or maybe you simply want to use a different proving system. Since Noir does not compile +to a specific proof system, it is possible for protocol developers to replace the PLONK-based +proving system with a different proving system altogether. + +### Blockchain developers + +As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the +proving system and smart contract language has been pre-defined). In order for you to use Noir in +your blockchain, a proving system backend and a smart contract interface +must be implemented for it. + +## What's new about Noir? + +Noir is simple and flexible in its design, as it does not compile immediately to a fixed +NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled +to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). + +This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. + +## Current Features + +Compiler: + +- Module System +- For expressions +- Arrays +- Bit Operations +- Binary operations (\<, \<=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] +- Unsigned integers +- If statements +- Structures and Tuples +- Generics + +ACIR Supported OPCODES: + +- Sha256 +- Blake2s +- Schnorr signature verification +- MerkleMembership +- Pedersen Commitment +- Pedersen Hash +- HashToField + +## Libraries + +Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). + +Some libraries that are available today include: + +- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library +- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) +- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers +- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address +- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees +- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir +- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers + +See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.19.4/language_concepts/01_functions.md new file mode 100644 index 0000000000..5eb22170e5 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/01_functions.md @@ -0,0 +1,225 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](../nargo/02_testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main([1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./06_generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./08_lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./05_unconstrained.md) and [NoirJS](../noir_js/noir_js.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../nargo/02_testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.19.4/language_concepts/02_control_flow.md new file mode 100644 index 0000000000..a7f8536019 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/02_control_flow.md @@ -0,0 +1,44 @@ +--- +title: Control Flow +description: + Learn how to use loops and if expressions in the Noir programming language. Discover the syntax + and examples for for loops and if-else statements. +keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +--- + +## Loops + +Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple +times. + +The following block of code between the braces is run 10 times. + +```rust +for i in 0..10 { + // do something +}; +``` + +The index for loops is of type `u64`. + +## If Expressions + +Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required +for the statement's conditional to be surrounded by parentheses. + +```rust +let a = 0; +let mut x: u32 = 0; + +if a == 0 { + if a != 0 { + x = 6; + } else { + x = 2; + } +} else { + x = 5; + assert(x == 5); +} +assert(x == 2); +``` diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md new file mode 100644 index 0000000000..d5caa46376 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/03_ops.md @@ -0,0 +1,97 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer | +| >> | Right shift an integer by another integer amount | Types must be integer | +| ! | Bitwise not of a value | Type must be integer or boolean | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | +| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | +| == | returns a bool if one value is equal to the other | Both types must not be constants | +| != | returns a bool if one value is not equal to the other | Both types must not be constants | + +### Predicate Operators + +`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. +This differs from the operations such as `+` where the operands are used in _computation_. + +### Bitwise Operations Example + +```rust +fn main(x : Field) { + let y = x as u32; + let z = y & y; +} +``` + +`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise +`&`. + +> `x & x` would not compile as `x` is a `Field` and not an integer type. + +### Logical Operators + +Noir has no support for the logical operators `||` and `&&`. This is because encoding the +short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can +use the bitwise operators `|` and `&` which operate indentically for booleans, just without the +short-circuiting. + +```rust +let my_val = 5; + +let mut flag = 1; +if (my_val > 6) | (my_val == 0) { + flag = 0; +} +assert(flag == 1); + +if (my_val != 10) & (my_val < 50) { + flag = 0; +} +assert(flag == 0); +``` + +### Shorthand operators + +Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: + +```rust +let mut i = 0; +i = i + 1; +``` + +could be written as: + +```rust +let mut i = 0; +i += 1; +``` diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.19.4/language_concepts/04_assert.md new file mode 100644 index 0000000000..7427ec6cc6 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/04_assert.md @@ -0,0 +1,26 @@ +--- +title: Assert Function +description: + Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or + comparison expression that follows to be true, and what happens if the expression is false at + runtime. +keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +--- + +Noir includes a special `assert` function which will explicitly constrain the predicate/comparison +expression that follows to be true. If this expression is false at runtime, the program will fail to +be proven. Example: + +```rust +fn main(x : Field, y : Field) { + assert(x == y); +} +``` + +You can optionally provide a message to be logged when the assertion fails: + +```rust +assert(x == y, "x and y are not equal"); +``` + +> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.19.4/language_concepts/05_unconstrained.md similarity index 100% rename from docs/versioned_docs/version-v0.9.0/language_concepts/05_unconstrained.md rename to docs/versioned_docs/version-v0.19.4/language_concepts/05_unconstrained.md diff --git a/docs/versioned_docs/version-v0.10.5/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.19.4/language_concepts/06_generics.md similarity index 100% rename from docs/versioned_docs/version-v0.10.5/language_concepts/06_generics.md rename to docs/versioned_docs/version-v0.19.4/language_concepts/06_generics.md diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.19.4/language_concepts/07_mutability.md new file mode 100644 index 0000000000..ad902c42c9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/07_mutability.md @@ -0,0 +1,92 @@ +--- +title: Mutability +description: + Learn about mutable variables, constants, and globals in Noir programming language. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Comptime Values + +:::warning + +The 'comptime' keyword was removed in version 0.10. The comptime keyword and syntax are currently still kept and parsed for backwards compatibility, but are now deprecated and will issue a warning when used. `comptime` has been removed because it is no longer needed for accessing arrays. + +::: + +## Globals + +Noir also supports global variables. However, they must be known at compile-time. The global type can also be inferred by the compiler entirely. Globals can also be used to specify array +annotations for function parameters and can be imported from submodules. + +```rust +global N: Field = 5; // Same as `global N: Field = 5` + +fn main(x : Field, y : [Field; N]) { + let res = x * N; + + assert(res == y[0]); + + let res2 = x * mysubmodule::N; + assert(res != res2); +} + +mod mysubmodule { + use dep::std; + + global N: Field = 10; + + fn my_helper() -> Field { + let x = N; + x + } +} +``` + +## Why only local mutability? + +Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting +without applying additional overhead to the user. Modeling a mutable reference is not as +straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/08_lambdas.md b/docs/versioned_docs/version-v0.19.4/language_concepts/08_lambdas.md new file mode 100644 index 0000000000..ae1e6aecab --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/08_lambdas.md @@ -0,0 +1,80 @@ +--- +title: Lambdas +description: Learn how to use anonymous functions in Noir programming language. +keywords: [Noir programming language, lambda, closure, function, anonymous function] +--- + +## Introduction + +Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +A block can be used as the body of a lambda, allowing you to declare local variables inside it: + +```rust +let cool = || { + let x = 100; + let y = 100; + x + y +} + +assert(cool() == 200); +``` + +## Closures + +Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: + +```rust +fn main() { + let x = 100; + let closure = || x + 150; + assert(closure() == 250); +} +``` + +## Passing closures to higher-order functions + +It may catch you by surprise that the following code fails to compile: + +```rust +fn foo(f: fn () -> Field) -> Field { + f() +} + +fn main() { + let (x, y) = (50, 50); + assert(foo(|| x + y) == 100); // error :( +} +``` + +The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` +expects a regular function as an argument - those are incompatible. +:::note + +Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. + +E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. + +::: +The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - +in this example that's `(Field, Field)`. + +The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called +with closures with any environment, as well as with regular functions: + +```rust +fn foo(f: fn[Env]() -> Field) -> Field { + f() +} + +fn main() { + let (x, y) = (50, 50); + assert(foo(|| x + y) == 100); // compiles fine + assert(foo(|| 60) == 60); // compiles fine +} +``` diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/08_comments.md b/docs/versioned_docs/version-v0.19.4/language_concepts/09_comments.md similarity index 100% rename from docs/versioned_docs/version-v0.9.0/language_concepts/08_comments.md rename to docs/versioned_docs/version-v0.19.4/language_concepts/09_comments.md diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/09_distinct.md b/docs/versioned_docs/version-v0.19.4/language_concepts/10_distinct.md similarity index 100% rename from docs/versioned_docs/version-v0.9.0/language_concepts/09_distinct.md rename to docs/versioned_docs/version-v0.19.4/language_concepts/10_distinct.md diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/10_shadowing.md b/docs/versioned_docs/version-v0.19.4/language_concepts/11_shadowing.md similarity index 100% rename from docs/versioned_docs/version-v0.9.0/language_concepts/10_shadowing.md rename to docs/versioned_docs/version-v0.19.4/language_concepts/11_shadowing.md diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types.md new file mode 100644 index 0000000000..d546cc463a --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types.md @@ -0,0 +1,96 @@ +--- +title: Data Types +description: + Get a clear understanding of the two categories of Noir data types - primitive types and compound + types. Learn about their characteristics, differences, and how to use them in your Noir + programming. +keywords: + [ + noir, + data types, + primitive types, + compound types, + private types, + public types, + ] +--- + +Every value in Noir has a type, which determines which operations are valid for it. + +All values in Noir are fundamentally composed of `Field` elements. For a more approachable +developing experience, abstractions are added on top to introduce different data types in Noir. + +Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound +types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or +public. + +## Private & Public Types + +A **private value** is known only to the Prover, while a **public value** is known by both the +Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All +primitive types (including individual fields of compound types) in Noir are private by default, and +can be marked public when certain values are intended to be revealed to the Verifier. + +> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once +> the proofs are verified on-chain the values can be considered known to everyone that has access to +> that blockchain. + +Public data types are treated no differently to private types apart from the fact that their values +will be revealed in proofs generated. Simply changing the value of a public type will not change the +circuit (where the same goes for changing values of private types as well). + +_Private values_ are also referred to as _witnesses_ sometimes. + +> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different +> meaning than when applied to a function (e.g. `pub fn foo() {}`). +> +> The former is a visibility modifier for the Prover to interpret if a value should be made known to +> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a +> function should be made accessible to external Noir programs like in other languages. + +### pub Modifier + +All data types in Noir are private by default. Types are explicitly declared as public using the +`pub` modifier: + +```rust +fn main(x : Field, y : pub Field) -> pub Field { + x + y +} +``` + +In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note +that visibility is handled **per variable**, so it is perfectly valid to have one input that is +private and another that is public. + +> **Note:** Public types can only be declared through parameters on `main`. + +## Type Aliases + +A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: + +```rust +type Id = u8; + +fn main() { + let id: Id = 1; + let zero: u8 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can also be used with [generics](./06_generics.md): + +```rust +type Id = Size; + +fn main() { + let id: Id = 1; + let zero: u32 = 0; + assert(zero + 1 == id); +} +``` + +### BigInt + +You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/00_fields.md new file mode 100644 index 0000000000..78d3d2af16 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/00_fields.md @@ -0,0 +1,165 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_le_bits(32); +} +``` + +### to_be_bits + +Transforms the field into an array of bits, Big Endian. + +```rust +fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_be_bits(32); +} +``` + +### to_le_bytes + +Transforms into an array of bytes, Little Endian + +```rust +fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_le_bytes(4); +} +``` + +### to_be_bytes + +Transforms into an array of bytes, Big Endian + +```rust +fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_be_bytes(4); +} +``` + +### to_le_radix + +Decomposes into a vector over the specified base, Little Endian + +```rust +fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_le_radix(256, 4); +} +``` + +### to_be_radix + +Decomposes into a vector over the specified base, Big Endian + +```rust +fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_be_radix(256, 4); +} +``` + +### pow_32 + +Returns the value to the power of the specified exponent + +```rust +fn pow_32(self, exponent: Field) -> Field +``` + +example: + +```rust +fn main() { + let field = 2 + let pow = field.pow_32(4); + assert(pow == 16); +} +``` + +### sgn0 + +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. + +```rust +fn sgn0(self) -> u1 +``` diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/01_integers.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/01_integers.md new file mode 100644 index 0000000000..b1e7ad11bf --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/01_integers.md @@ -0,0 +1,112 @@ +--- +title: Integers +description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. +keywords: [noir, integer types, methods, examples, arithmetic] +--- + +An integer type is a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed integer types. + +:::info + +When an integer is defined in Noir without a specific type, it will default to `Field`. + +The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. + +::: + +## Unsigned Integers + +An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): + +```rust +fn main() { + let x: u8 = 1; + let y: u8 = 1; + let z = x + y; + assert (z == 2); +} +``` + +The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). + +## Signed Integers + +A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): + +```rust +fn main() { + let x: i8 = -1; + let y: i8 = -1; + let z = x + y; + assert (z == -2); +} +``` + +The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). + +:::tip + +If you are using the default proving backend with Noir, both even (e.g. _u2_, _i2_) and odd (e.g. _u3_, _i3_) arbitrarily-sized integer types up to 127 bits (i.e. _u127_ and _i127_) are supported. + +::: + +## Overflows + +Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: + +```rust +fn main(x: u8, y: u8) { + let z = x + y; +} +``` + +With: + +```toml +x = "255" +y = "1" +``` + +Would result in: + +``` +$ nargo prove +error: Assertion failed: 'attempt to add with overflow' +┌─ ~/src/main.nr:9:13 +│ +│ let z = x + y; +│ ----- +│ += Call stack: + ... +``` + +A similar error would happen with signed integers: + +```rust +fn main() { + let x: i8 = -118; + let y: i8 = -11; + let z = x + y; +} +``` + +### Wrapping methods + +Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: + +```rust +fn wrapping_add(x: T, y: T) -> T; +fn wrapping_sub(x: T, y: T) -> T; +fn wrapping_mul(x: T, y: T) -> T; +``` + +Example of how it is used: + +```rust +use dep::std; + +fn main(x: u8, y: u8) -> pub u8 { + std::wrapping_add(x + y) +} +``` diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md new file mode 100644 index 0000000000..885db167d8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md @@ -0,0 +1,30 @@ +--- +title: Booleans +description: + Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. +keywords: + [ + noir, + boolean type, + methods, + examples, + logical operations, + ] +--- + + +The `bool` type in Noir has two possible values: `true` and `false`: + +```rust +fn main() { + let t = true; + let f: bool = false; +} +``` + +> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for +> `false` in _Verifier.toml_. + +The boolean type is most commonly used in conditionals like `if` expressions and `assert` +statements. More about conditionals is covered in the [Control Flow](../control_flow) and +[Assert Function](../assert) sections. diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md new file mode 100644 index 0000000000..b4c75942bb --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md @@ -0,0 +1,88 @@ +--- +title: Strings +description: + Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. +keywords: + [ + noir, + string type, + methods, + examples, + concatenation, + ] +--- + + +The string type is a fixed length value defined with `str`. + +You can use strings in `assert()` functions or print them with `std::println()`. See more about [Logging](../../standard_library/logging). + +```rust +use dep::std; + +fn main(message : pub str<11>, hex_as_string : str<4>) { + std::println(message); + assert(message == "hello world"); + assert(hex_as_string == "0x41"); +} +``` + +You can convert a `str` to a byte array by calling `as_bytes()` +or a vector by calling `as_bytes_vec()`. + +```rust +fn main() { + let message = "hello world"; + let message_bytes = message.as_bytes(); + let mut message_vec = message.as_bytes_vec(); + assert(message_bytes.len() == 11); + assert(message_bytes[0] == 104); + assert(message_bytes[0] == message_vec.get(0)); +} +``` + +## Escape Characters + +You can use escape characters for your strings: + +| Escape Sequence | Description | +|-----------------|-----------------| +| `\r` | Carriage Return | +| `\n` | Newline | +| `\t` | Tab | +| `\0` | Null Character | +| `\"` | Double Quote | +| `\\` | Backslash | + +Example: + +```rust +let s = "Hello \"world"; // prints "Hello "world" +let s = "hey \tyou"; // prints "hey you" +``` + +## Formatted Strings + +You can prepend a string with the singular `f` token to create a formatted string. This is useful when logging, as it allows injection of local variables: + +```rust +let var = 15; +std::println(f"var {var}") // prints "var 0x0F" + +let var = -1 as u8; +std::println(f"var {var}") // prints "var 255" + +let var : i8 = -1; +std::println(f"var {var}") // prints "var -1" + +// prints "Hello +//world" +std::println(f"Hello +world"); + +std::println(f"hey \tyou"); // prints "hey \tyou" +``` + +A type can be specified to print numbers either as hex via `Field`, unsigned via `u*` types and signed via `i*` types. + +Note that escaped characters in formatted strings `fmtstr` will be outputted as defined, i.e. "\n" will be printed `\n`, not as a new line. You can add a newline or other whitespace by creating a multiline string as in the example above. diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md new file mode 100644 index 0000000000..bdbd1798be --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md @@ -0,0 +1,244 @@ +--- +title: Arrays +description: + Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. +keywords: + [ + noir, + array type, + methods, + examples, + indexing, + ] +--- + +An array is one way of grouping together values into one compound type. Array types can be inferred +or explicitly specified via the syntax `[; ]`: + +```rust +fn main(x : Field, y : Field) { + let my_arr = [x, y]; + let your_arr: [Field; 2] = [x, y]; +} +``` + +Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. + +Array elements can be accessed using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group +a `Field` value and a `u8` value together for example. + +You can write mutable arrays, like: + +```rust +fn main() { + let mut arr = [1, 2, 3, 4, 5]; + assert(arr[0] == 1); + + arr[0] = 42; + assert(arr[0] == 42); +} +``` + +You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. + +```rust +let array: [Field; 32] = [0; 32]; +``` + +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: + +```rust +let array: [Field; 32] = [0; 32]; +let sl = array.as_slice() +``` + +You can define multidimensional arrays: + +```rust +let array : [[Field; 2]; 2]; +let element = array[0][0]; +``` + +## Types + +You can create arrays of primitive types or structs. There is not yet support for nested arrays +(arrays of arrays) or arrays of structs that contain arrays. + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for arrays: + +### len + +Returns the length of an array + +```rust +fn len(_array: [T; N]) -> comptime Field +``` + +example + +```rust +fn main() { + let array = [42, 42]; + assert(array.len() == 2); +} +``` + +### sort + +Returns a new sorted array. The original array remains untouched. Notice that this function will +only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting +logic it uses internally is optimized specifically for these values. If you need a sort function to +sort any type, you should use the function `sort_via` described below. + +```rust +fn sort(_array: [T; N]) -> [T; N] +``` + +example + +```rust +fn main() { + let arr = [42, 32]; + let sorted = arr.sort(); + assert(sorted == [32, 42]); +} +``` + +### sort_via + +Sorts the array with a custom comparison function + +```rust +fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] +``` + +example + +```rust +fn main() { + let arr = [42, 32] + let sorted_ascending = arr.sort_via(|a, b| a < b); + assert(sorted_ascending == [32, 42]); // verifies + + let sorted_descending = arr.sort_via(|a, b| a > b); + assert(sorted_descending == [32, 42]); // does not verify +} +``` + +### map + +Applies a function to each element of the array, returning a new array containing the mapped elements. + +```rust +fn map(f: fn(T) -> U) -> [U; N] +``` + +example + +```rust +let a = [1, 2, 3]; +let b = a.map(|a| a * 2); // b is now [2, 4, 6] +``` + +### fold + +Applies a function to each element of the array, returning the final accumulated value. The first +parameter is the initial value. + +```rust +fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U +``` + +This is a left fold, so the given function will be applied to the accumulator and first element of +the array, then the second, and so on. For a given call the expected result would be equivalent to: + +```rust +let a1 = [1]; +let a2 = [1, 2]; +let a3 = [1, 2, 3]; + +let f = |a, b| a - b; +a1.fold(10, f) //=> f(10, 1) +a2.fold(10, f) //=> f(f(10, 1), 2) +a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) +``` + +example: + +```rust + +fn main() { + let arr = [2, 2, 2, 2, 2]; + let folded = arr.fold(0, |a, b| a + b); + assert(folded == 10); +} + +``` + +### reduce + +Same as fold, but uses the first element as starting element. + +```rust +fn reduce(f: fn(T, T) -> T) -> T +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 2]; + let reduced = arr.reduce(|a, b| a + b); + assert(reduced == 10); +} +``` + +### all + +Returns true if all the elements satisfy the given predicate + +```rust +fn all(predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 2]; + let all = arr.all(|a| a == 2); + assert(all); +} +``` + +### any + +Returns true if any of the elements satisfy the given predicate + +```rust +fn any(predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 5]; + let any = arr.any(|a| a == 5); + assert(any); +} + +``` diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/05_slices.mdx b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/05_slices.mdx new file mode 100644 index 0000000000..1be0ec4a13 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/05_slices.mdx @@ -0,0 +1,146 @@ +--- +title: Slices +description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. +keywords: [noir, slice type, methods, examples, subarrays] +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. + +```rust +use dep::std::slice; + +fn main() -> pub Field { + let mut slice: [Field] = [0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for slices: + +### push_back + +Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. + +```rust +fn push_back(_self: [T], _elem: T) -> [T] +``` + +example: + +```rust +fn main() -> pub Field { + let mut slice: [Field] = [0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +### push_front + +Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. + +```rust +fn push_front(_self: Self, _elem: T) -> Self +``` + +Example: + +```rust +let mut new_slice: [Field] = []; +new_slice = new_slice.push_front(20); +assert(new_slice[0] == 20); // returns true +``` + +View the corresponding test file [here][test-file]. + +### pop_front + +Returns a tuple of two items, the first element of the array and the rest of the array. + +```rust +fn pop_front(_self: Self) -> (T, Self) +``` + +Example: + +```rust +let (first_elem, rest_of_slice) = slice.pop_front(); +``` + +View the corresponding test file [here][test-file]. + +### pop_back + +Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. + +```rust +fn pop_back(_self: Self) -> (Self, T) +``` + +Example: + +```rust +let (popped_slice, last_elem) = slice.pop_back(); +``` + +View the corresponding test file [here][test-file]. + +### append + +Loops over a slice and adds it to the end of another. + +```rust +fn append(mut self, other: Self) -> Self +``` + +Example: + +```rust +let append = [1, 2].append([3, 4, 5]); +``` + +### insert + +Inserts an element at a specified index and shifts all following elements by 1. + +```rust +fn insert(_self: Self, _index: Field, _elem: T) -> Self +``` + +Example: + +```rust +new_slice = rest_of_slice.insert(2, 100); +assert(new_slice[2] == 100); +``` + +View the corresponding test file [here][test-file]. + +### remove + +Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. + +```rust +fn remove(_self: Self, _index: Field) -> (Self, T) +``` + +Example: + +```rust +let (remove_slice, removed_elem) = slice.remove(3); +``` diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/06_vectors.mdx b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/06_vectors.mdx new file mode 100644 index 0000000000..4617e90d03 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/06_vectors.mdx @@ -0,0 +1,172 @@ +--- +title: Vectors +description: Delve into the Vector data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. +keywords: [noir, vector type, methods, examples, dynamic arrays] +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. + +Example: + +```rust +use dep::std::collections::vec::Vec; + +let mut vector: Vec = Vec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +``` + +## Methods + +### new + +Creates a new, empty vector. + +```rust +pub fn new() -> Self { + Self { slice: [] } +} +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### from_slice + +Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. + +```rust +pub fn from_slice(slice: [T]) -> Self { + Self { slice } +} +``` + +Example: + +```rust +let arr: [Field] = [1, 2, 3]; +let vector_from_slice = Vec::from_slice(arr); +assert(vector_from_slice.len() == 3); +``` + +### get + +Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. + +```rust +pub fn get(self, index: Field) -> T { + self.slice[index] +} +``` + +Example: + +```rust +let vector: Vec = Vec::from_slice([10, 20, 30]); +assert(vector.get(1) == 20); +``` + +### push + +Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. + +```rust +pub fn push(&mut self, elem: T) { + self.slice = self.slice.push_back(elem); +} +``` + +Example: + +```rust +let mut vector: Vec = Vec::new(); +vector.push(10); +assert(vector.len() == 1); +``` + +### pop + +Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. + +```rust +pub fn pop(&mut self) -> T { + let (popped_slice, last_elem) = self.slice.pop_back(); + self.slice = popped_slice; + last_elem +} +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 20]); +let popped_elem = vector.pop(); +assert(popped_elem == 20); +assert(vector.len() == 1); +``` + +### insert + +Inserts an element at a specified index, shifting subsequent elements to the right. + +```rust +pub fn insert(&mut self, index: Field, elem: T) { + self.slice = self.slice.insert(index, elem); +} +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 30]); +vector.insert(1, 20); +assert(vector.get(1) == 20); +``` + +### remove + +Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. + +```rust +pub fn remove(&mut self, index: Field) -> T { + let (new_slice, elem) = self.slice.remove(index); + self.slice = new_slice; + elem +} +``` + +Example: + +```rust +let mut vector = Vec::from_slice([10, 20, 30]); +let removed_elem = vector.remove(1); +assert(removed_elem == 20); +assert(vector.len() == 2); +``` + +### len + +Returns the number of elements in the vector. + +```rust +pub fn len(self) -> Field { + self.slice.len() +} +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/07_tuples.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/07_tuples.md new file mode 100644 index 0000000000..5f6cab974a --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/07_tuples.md @@ -0,0 +1,47 @@ +--- +title: Tuples +description: + Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. +keywords: + [ + noir, + tuple type, + methods, + examples, + multi-value containers, + ] +--- + +A tuple collects multiple values like an array, but with the added ability to collect values of +different types: + +```rust +fn main() { + let tup: (u8, u64, Field) = (255, 500, 1000); +} +``` + +One way to access tuple elements is via destructuring using pattern matching: + +```rust +fn main() { + let tup = (1, 2); + + let (one, two) = tup; + + let three = one + two; +} +``` + +Another way to access tuple elements is via direct member access, using a period (`.`) followed by +the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to +the second and so on: + +```rust +fn main() { + let tup = (5, 6, 7, 8); + + let five = tup.0; + let eight = tup.3; +} +``` diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/08_structs.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/08_structs.md new file mode 100644 index 0000000000..3542173463 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/08_structs.md @@ -0,0 +1,69 @@ +--- +title: Structs +description: + Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. +keywords: + [ + noir, + struct type, + methods, + examples, + data structures, + ] +--- + +A struct also allows for grouping multiple values of different types. Unlike tuples, we can also +name each field. + +> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the +> field type of Noir. + +Defining a struct requires giving it a name and listing each field within as `: ` pairs: + +```rust +struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +An instance of a struct can then be created with actual values in `: ` pairs in any +order. Struct fields are accessible using their given names: + +```rust +fn main() { + let legs = 4; + + let dog = Animal { + eyes: 2, + hands: 0, + legs, + }; + + let zero = dog.hands; +} +``` + +Structs can also be destructured in a pattern, binding each field to a new variable: + +```rust +fn main() { + let Animal { hands, legs: feet, eyes } = get_octopus(); + + let ten = hands + feet + eyes as u8; +} + +fn get_octopus() -> Animal { + let octopus = Animal { + hands: 0, + legs: 8, + eyes: 2, + }; + + octopus +} +``` + +The new variables can be bound with names different from the original struct field names, as +showcased in the `legs --> feet` binding in the example above. diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/09_references.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/09_references.md new file mode 100644 index 0000000000..b0c35ce2cb --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/09_references.md @@ -0,0 +1,22 @@ +--- +title: References +--- + +Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. + +Example: + +```rust +fn main() { + let mut x = 2; + + // you can reference x as &mut and pass it to multiplyBy2 + multiplyBy2(&mut x); +} + +// you can access &mut here +fn multiplyBy2(x: &mut Field) { + // and dereference it with * + *x = *x * 2; +} +``` diff --git a/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/10_function_types.md b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/10_function_types.md new file mode 100644 index 0000000000..1ec92efd59 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/10_function_types.md @@ -0,0 +1,25 @@ +--- +title: Function types +--- + +Noir supports higher-order functions. The syntax for a function type is as follows: + +```rust +fn(arg1_type, arg2_type, ...) -> return_type +``` + +Example: + +```rust +fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field + assert(f() == 100); +} + +fn main() { + assert_returns_100(|| 100); // ok + assert_returns_100(|| 150); // fails +} +``` + +A function type also has an optional capture environment - this is necessary to support closures. +See [Lambdas](../08_lambdas.md) for more details. diff --git a/docs/versioned_docs/version-v0.19.4/migration_notes.md b/docs/versioned_docs/version-v0.19.4/migration_notes.md new file mode 100644 index 0000000000..0d7e0af0ef --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/migration_notes.md @@ -0,0 +1,91 @@ +--- +title: Migration notes +description: Read about migration notes from previous versions, which could solve problems while updating +keywords: [Noir, notes, migration, updating, upgrading] +--- + +Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. + +## ≥0.19 + +### Enforcing `compiler_version` + +From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. + +To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. + +## ≥0.14 + +The index of the [for loops](./language_concepts/02_control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: + +```rust +for i in 0..10 { + let i = i as Field; +} +``` + +## ≥v0.11.0 and Nargo backend + +From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: + +### `backend encountered an error` + +This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. + +To fix the issue: + +1. Uninstall the existing backend + +```bash +nargo backend uninstall acvm-backend-barretenberg +``` + +You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. + +2. Reinstall a compatible version of the proving backend. + +If you are using the default barretenberg backend, simply run: + +``` +nargo prove +``` + +with you Noir program. + +This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. + +### `backend encountered an error: illegal instruction` + +On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. + +To fix the issue: + +1. Uninstall the existing backend + +```bash +nargo backend uninstall acvm-backend-barretenberg +``` + +You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. + +2. Reinstall a compatible version of the proving backend. + +If you are using the default barretenberg backend, simply run: + +``` +nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz +``` + +This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. + +The gzipped filed is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. + +Then run: + +``` +DESIRED_BINARY_VERSION=0.8.1 nargo info +``` + +This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. + +0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/crates_and_packages.md new file mode 100644 index 0000000000..fb83a33d94 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/crates_and_packages.md @@ -0,0 +1,42 @@ +--- +title: Crates and Packages +description: Learn how to use Crates and Packages in your Noir project +keywords: [Nargo, dependencies, package management, crates, package] +--- + +## Crates + +A crate is the smallest amount of code that the Noir compiler considers at a time. +Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. + +### Crate Types + +A Noir crate can come in several forms: binaries, libraries or contracts. + +#### Binaries + +_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. + +#### Libraries + +_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. + +#### Contracts + +Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/noir-contracts/src/contracts). + +### Crate Root + +Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. + +## Packages + +A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. + +A package _must_ contain either a library or a binary crate, but not both. + +### Differences from Cargo Packages + +One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. + +In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md new file mode 100644 index 0000000000..75f95aaa30 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md @@ -0,0 +1,123 @@ +--- +title: Dependencies +description: + Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub + and use them easily in your project. +keywords: [Nargo, dependencies, GitHub, package management, versioning] +--- + +Nargo allows you to upload packages to GitHub and use them as dependencies. + +## Specifying a dependency + +Specifying a dependency requires a tag to a specific commit and the git url to the url containing +the package. + +Currently, there are no requirements on the tag contents. If requirements are added, it would follow +semver 2.0 guidelines. + +> Note: Without a `tag` , there would be no versioning and dependencies would change each time you +> compile your project. + +For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: + +```toml +# Nargo.toml + +[dependencies] +ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} +``` + +If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: + +```toml +# Nargo.toml + +[dependencies] +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "yarn-project/noir-contracts/src/contracts/easy_private_token_contract"} +``` + +## Specifying a local dependency + +You can also specify dependencies that are local to your machine. + +For example, this file structure has a library and binary crate + +```tree +├── binary_crate +│   ├── Nargo.toml +│   └── src +│   └── main.nr +└── liba + ├── Nargo.toml + └── src + └── lib.nr +``` + +Inside of the binary crate, you can specify: + +```toml +# Nargo.toml + +[dependencies] +libA = { path = "../liba" } +``` + +## Importing dependencies + +You can import a dependency to a Noir file using the following syntax. For example, to import the +ecrecover-noir library and local liba referenced above: + +```rust +use dep::ecrecover; +use dep::libA; +``` + +You can also import only the specific parts of dependency that you want to use, like so: + +```rust +use dep::std::hash::sha256; +use dep::std::scalar_mul::fixed_base_embedded_curve; +``` + +Lastly, as demonstrated in the +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +can import multiple items in the same line by enclosing them in curly braces: + +```rust +use dep::std::ec::tecurve::affine::{Curve, Point}; +``` + +We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. + +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +## Dependencies of Dependencies + +Note that when you import a dependency, you also get access to all of the dependencies of that package. + +For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: + +```rust +use dep::phy_vector; + +fn main(x : Field, y : pub Field) { + //... + let f = phy_vector::fraction::toFraction(true, 2, 1); + //... +} +``` + +## Available Libraries + +Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). + +Some libraries that are available today include: + +- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library +- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) +- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers +- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address +- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees +- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir +- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/modules.md new file mode 100644 index 0000000000..147c9b284e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/modules.md @@ -0,0 +1,104 @@ +--- +title: Modules +description: + Learn how to organize your files using modules in Noir, following the same convention as Rust's + module system. Examples included. +keywords: [Noir, Rust, modules, organizing files, sub-modules] +--- + +Noir's module system follows the same convention as the _newer_ version of Rust's module system. + +## Purpose of Modules + +Modules are used to organise files. Without modules all of your code would need to live in a single +file. In Noir, the compiler does not automatically scan all of your files to detect modules. This +must be done explicitly by the developer. + +## Examples + +### Importing a module in the crate root + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::hello_world(); +} +``` + +Filename : `src/foo.nr` + +```rust +fn from_foo() {} +``` + +In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module +declaration `mod foo` which prompts it to look for a foo.nr file. + +Visually this module hierarchy looks like the following : + +``` +crate + ├── main + │ + └── foo + └── from_foo + +``` + +### Importing a module throughout the tree + +All modules are accessible from the `crate::` namespace. + +``` +crate + ├── bar + ├── foo + └── main + +``` + +In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. + +### Sub-modules + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::from_foo(); +} +``` + +Filename : `src/foo.nr` + +```rust +mod bar; +fn from_foo() {} +``` + +Filename : `src/foo/bar.nr` + +```rust +fn from_bar() {} +``` + +In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule +of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the +compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` + +Visually the module hierarchy looks as follows: + +``` +crate + ├── main + │ + └── foo + ├── from_foo + └── bar + └── from_bar +``` diff --git a/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md new file mode 100644 index 0000000000..a979ef9f0a --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md @@ -0,0 +1,39 @@ +--- +title: Workspaces +--- + +Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. + +Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. + +For a project with the following structure: + +```tree +├── crates +│   ├── a +│   │   ├── Nargo.toml +│   │   └── src +│   │   └── main.nr +│   └── b +│   ├── Nargo.toml +│   └── src +│   └── main.nr +├── Nargo.toml +└── Prover.toml +``` + +You can define a workspace in Nargo.toml like so: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. + +`default-member` indicates which package various commands process by default. + +Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md b/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md new file mode 100644 index 0000000000..65e2bdb44e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md @@ -0,0 +1,250 @@ +--- +title: Commands +description: + Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, + generate Solidity verifier smart contract and compile into JSON file containing ACIR + representation and ABI of circuit. +keywords: + [ + Nargo, + Noir CLI, + Noir Prover, + Noir Verifier, + generate Solidity verifier, + compile JSON file, + ACIR representation, + ABI of circuit, + TypeScript, + ] +--- + +## General options + +| Option | Description | +| -------------------- | -------------------------------------------------- | +| `--show-ssa` | Emit debug information for the intermediate SSA IR | +| `--deny-warnings` | Quit execution when warnings are emitted | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo help [subcommand]` + +Prints the list of available commands or specific information of a subcommand. + +_Arguments_ + +| Argument | Description | +| -------------- | -------------------------------------------- | +| `` | The subcommand whose help message to display | + +## `nargo backend` + +Installs and selects custom backends used to generate and verify proofs. + +### Commands + +| Command | Description | +| ----------- | --------------------------------------------------------- | +| `current` | Prints the name of the currently active backend | +| `ls` | Prints the list of currently installed backends | +| `use` | Select the backend to use | +| `install` | Install a new backend from a URL | +| `uninstall` | Uninstalls a backend | +| `help` | Print this message or the help of the given subcommand(s) | + +### Options + +| Option | Description | +| ------------ | ----------- | +| `-h, --help` | Print help | + +## `nargo check` + +Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output +values of the Noir program respectively. + +### Options + +| Option | Description | +| --------------------- | ------------------------------------- | +| `--package ` | The name of the package to check | +| `--workspace` | Check all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +### `nargo codegen-verifier` + +Generate a Solidity verifier smart contract for the program. + +### Options + +| Option | Description | +| --------------------- | ------------------------------------- | +| `--package ` | The name of the package to codegen | +| `--workspace` | Codegen all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo compile` + +Compile the program into a JSON build artifact file containing the ACIR representation and the ABI +of the circuit. This build artifact can then be used to generate and verify proofs. + +You can also use "build" as an alias for compile (e.g. `nargo build`). + +### Options + +| Option | Description | +| --------------------- | ------------------------------------------------------------ | +| `--include-keys` | Include Proving and Verification keys in the build artifacts | +| `--package ` | The name of the package to compile | +| `--workspace` | Compile all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo new ` + +Creates a new Noir project in a new folder. + +**Arguments** + +| Argument | Description | +| -------- | -------------------------------- | +| `` | The path to save the new project | + +### Options + +| Option | Description | +| --------------- | ----------------------------------------------------- | +| `--name ` | Name of the package [default: package directory name] | +| `--lib` | Use a library template | +| `--bin` | Use a binary template [default] | +| `--contract` | Use a contract template | +| `-h, --help` | Print help | + +## `nargo init` + +Creates a new Noir project in the current directory. + +### Options + +| Option | Description | +| --------------- | ----------------------------------------------------- | +| `--name ` | Name of the package [default: current directory name] | +| `--lib` | Use a library template | +| `--bin` | Use a binary template [default] | +| `--contract` | Use a contract template | +| `-h, --help` | Print help | + +## `nargo execute [WITNESS_NAME]` + +Runs the Noir program and prints its return value. + +**Arguments** + +| Argument | Description | +| ---------------- | ----------------------------------------- | +| `[WITNESS_NAME]` | Write the execution witness to named file | + +### Options + +| Option | Description | +| --------------------------------- | ------------------------------------------------------------------------------------ | +| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | +| `--package ` | The name of the package to execute | +| `--workspace` | Execute all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +_Usage_ + +The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which +must be filled in. + +To save the witness to file, run the command with a value for the `WITNESS_NAME` argument. A +`.tr` file will then be saved in the `./target` folder. + +## `nargo prove` + +Creates a proof for the program. + +### Options + +| Option | Description | +| ------------------------------------- | ---------------------------------------------------------------------------------------- | +| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover] | +| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | +| `--verify` | Verify proof after proving | +| `--package ` | The name of the package to prove | +| `--workspace` | Prove all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo verify` + +Given a proof and a program, verify whether the proof is valid. + +### Options + +| Option | Description | +| ------------------------------------- | ---------------------------------------------------------------------------------------- | +| `-v, --verifier-name ` | The name of the toml file which contains the inputs for the verifier [default: Verifier] | +| `--package ` | The name of the package to verify | +| `--workspace` | Verify all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo test [TEST_NAME]` + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. To print `println` statements in tests, use the `--show-output` flag. + +Takes an optional `--exact` flag which allows you to select tests based on an exact name. + +See an example on the [testing page](./testing). + +### Options + +| Option | Description | +| --------------------- | -------------------------------------- | +| `--show-output` | Display output of `println` statements | +| `--exact` | Only run tests that match exactly | +| `--package ` | The name of the package to test | +| `--workspace` | Test all packages in the workspace | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +## `nargo info` + +Prints a table containing the information of the package. + +Currently the table provide + +1. The number of ACIR opcodes +2. The final number gates in the circuit used by a backend + +If the file contains a contract the table will provide the +above information about each function of the contract. + +## `nargo lsp` + +Start a long-running Language Server process that communicates over stdin/stdout. +Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). + +## `nargo fmt` + +Automatically formats your Noir source code based on the default formatting settings. diff --git a/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md new file mode 100644 index 0000000000..da767274ef --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/nargo/02_testing.md @@ -0,0 +1,61 @@ +--- +title: Testing in Noir +description: Learn how to use Nargo to test your Noir program in a quick and easy way +keywords: [Nargo, testing, Noir, compile, test] +--- + +You can test your Noir programs using Noir circuits. + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. + +For example if you have a program like: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test] +fn test_add() { + assert(add(2,2) == 4); + assert(add(0,1) == 1); + assert(add(1,0) == 1); +} +``` + +Running `nargo test` will test that the `test_add` function can be executed while satisfying the all +the contraints which allows you to test that add returns the expected values. Test functions can't +have any arguments currently. + +### Test fail + +You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test(should_fail)] +fn test_add() { + assert(add(2,2) == 5); +} +``` + +You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: + +```rust +fn main(african_swallow_avg_speed : Field) { + assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); +} + +#[test] +fn test_king_arthur() { + main(65); +} + +#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] +fn test_bridgekeeper() { + main(32); +} + +``` diff --git a/docs/versioned_docs/version-v0.7.1/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.19.4/nargo/03_solidity_verifier.md similarity index 100% rename from docs/versioned_docs/version-v0.7.1/nargo/03_solidity_verifier.md rename to docs/versioned_docs/version-v0.19.4/nargo/03_solidity_verifier.md diff --git a/docs/versioned_docs/version-v0.19.4/nargo/04_language_server.md b/docs/versioned_docs/version-v0.19.4/nargo/04_language_server.md new file mode 100644 index 0000000000..48c01465f6 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/nargo/04_language_server.md @@ -0,0 +1,42 @@ +--- +title: Language Server +description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. +keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +--- + +This section helps you install and configure the Noir Language Server. + +The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. + +## Language Server + +The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. +As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! + +If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. + +## Language Client + +The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. + +Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). +> +> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. + +When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: + +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) + +You should also see your tests in the `testing` panel: + +![Testing panel](@site/static/img/codelens_testing_panel.png) + +### Configuration + +- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. +- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. +- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. +- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/getting_started/01_tiny_noir_app.md b/docs/versioned_docs/version-v0.19.4/noir_js/getting_started/01_tiny_noir_app.md new file mode 100644 index 0000000000..c51ed61de5 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/getting_started/01_tiny_noir_app.md @@ -0,0 +1,260 @@ +--- +title: End-to-end +description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment +keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs] +--- + +NoirJS works both on the browser and on the server, and works for both ESM and CJS module systems. In this page, we will learn how can we write a simple test and a simple web app to verify the standard Noir example. + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Before we start + +:::note + +Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.18.x matches `noir_js@0.18.x`, etc. + +In this guide, we will be pinned to 0.17.0. + +::: + +Make sure you have Node installed on your machine by opening a terminal and executing `node --version`. If you don't see a version, you should install [node](https://github.com/nvm-sh/nvm). You can also use `yarn` if you prefer that package manager over npm (which comes with node). + +First of all, follow the the [Nargo guide](../../getting_started/00_nargo_installation.md) to install nargo version 0.17.0 and create a new project with `nargo new circuit`. Once there, `cd` into the `circuit` folder. You should then be able to compile your circuit into `json` format and see it inside the `target` folder: + +```bash +nargo compile +``` + +Your folder structure should look like: + +```tree +. +└── circuit + ├── Nargo.toml + ├── src + │ └── main.nr + └── target + └── circuit.json +``` + +## Starting a new project + +Go back to the previous folder and start a new project by running run `npm init`. You can configure your project or just leave the defaults, and see a `package.json` appear in your root folder. + +## Installing dependencies + +We'll need two `npm` packages. These packages will provide us the methods we need to run and verify proofs: + +```bash +npm i @noir-lang/backend_barretenberg@^0.17.0 @noir-lang/noir_js@^0.17.0 +``` + +To serve our page, we can use a build tool such as `vite`. Because we're gonna use some `wasm` files, we need to install a plugin as well. Run: + +```bash +npm i --save-dev vite rollup-plugin-copy +``` + +Since we're on the dependency world, we may as well define a nice starting script. Vite makes it easy. Just open `package.json`, find the block "scripts" and add this just below the line with `"test" : "echo......."`: + +```json + "start": "vite --open" +``` + +If you want do build a static website, you can also add some build and preview scripts: + +```json + "build": "vite build", + "preview": "vite preview" +``` + +## Vite plugins + +Vite is great, but support from `wasm` doesn't work out-of-the-box. We're gonna write a quick plugin and use another one. Just copy and paste this into a file named `vite.config.js`. You don't need to understand it, just trust me bro. + +```js +import { defineConfig } from 'vite'; +import copy from 'rollup-plugin-copy'; +import fs from 'fs'; +import path from 'path'; + +const wasmContentTypePlugin = { + name: 'wasm-content-type-plugin', + configureServer(server) { + server.middlewares.use(async (req, res, next) => { + if (req.url.endsWith('.wasm')) { + res.setHeader('Content-Type', 'application/wasm'); + const newPath = req.url.replace('deps', 'dist'); + const targetPath = path.join(__dirname, newPath); + const wasmContent = fs.readFileSync(targetPath); + return res.end(wasmContent); + } + next(); + }); + }, +}; + +export default defineConfig(({ command }) => { + if (command === 'serve') { + return { + plugins: [ + copy({ + targets: [{ src: 'node_modules/**/*.wasm', dest: 'node_modules/.vite/dist' }], + copySync: true, + hook: 'buildStart', + }), + command === 'serve' ? wasmContentTypePlugin : [], + ], + }; + } + + return {}; +}); +``` + +## HTML + +Here's the simplest HTML with some terrible UI. Create a file called `index.html` and paste this: + +```html + + + + + + +

Very basic Noir app

+
+

Logs

+

Proof

+
+ + +``` + +## Some good old vanilla Javascript + +Create a new file `app.js`, which is where our javascript code will live. Let's start with this code inside: + +```js +document.addEventListener('DOMContentLoaded', async () => { + // here's where the magic happens +}); + +function display(container, msg) { + const c = document.getElementById(container); + const p = document.createElement('p'); + p.textContent = msg; + c.appendChild(p); +} +``` + +We can manipulate our website with this little function, so we can see our website working. + +## Adding Noir + +If you come from the previous page, your folder structure should look like this: + +```tree +├── app.js +├── circuit +│ ├── Nargo.toml +│ ├── src +│ │ └── main.nr +│ └── target +│ └── circuit.json +├── index.html +├── package.json +└── vite.config.js +``` + +You'll see other files and folders showing up (like `package-lock.json`, `yarn.lock`, `node_modules`) but you shouldn't have to care about those. + +## Importing our dependencies + +We're starting with the good stuff now. At the top of the new javascript file, import the packages: + +```ts +import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; +``` + +We also need to import the `circuit` JSON file we created. If you have the suggested folder structure, you can add this line: + +```ts +import circuit from './circuit/target/circuit.json'; +``` + +## Write code + +:::note + +We're gonna be adding code inside the `document.addEventListener...etc` block: + +```js +// forget stuff here +document.addEventListener('DOMContentLoaded', async () => { + // here's where the magic happens +}); +// forget stuff here +``` + +::: + +Our dependencies exported two classes: `BarretenbergBackend` and `Noir`. Let's `init` them and add some logs, just to flex: + +```ts +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit, backend); +``` + +## Proving + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +const input = { x: 1, y: 2 }; +display('logs', 'Generating proof... ⌛'); +const proof = await noir.generateFinalProof(input); +display('logs', 'Generating proof... ✅'); +display('results', proof.proof); +``` + +You're probably eager to see stuff happening, so go and run your app now! + +From your terminal, run `npm start` (or `yarn start`). If it doesn't open a browser for you, just visit `localhost:5173`. On a modern laptop, proof will generate in less than 100ms, and you'll see this: + +![Getting Started 0](@site/static/img/noir_getting_started_1.png) + +If you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human. + +In any case, this means your proof was generated! But you shouldn't trust me just yet. Add these lines to see it being verified: + +```js +display('logs', 'Verifying proof... ⌛'); +const verification = await noir.verifyFinalProof(proof); +if (verification) display('logs', 'Verifying proof... ✅'); +``` + +By saving, your app will refresh and here's our complete Tiny Noir App! + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Further Reading + +You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/next-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. + +You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/noir_js.md b/docs/versioned_docs/version-v0.19.4/noir_js/noir_js.md new file mode 100644 index 0000000000..f895b22eaf --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/noir_js.md @@ -0,0 +1,36 @@ +--- +title: NoirJS +description: Interact with Noir in Typescript or Javascript +keywords: [Noir project, javascript, typescript, node.js, browser, react] +--- + +NoirJS is a TypeScript library that make it easy to use Noir on your dapp, webapp, Node.js server, website, etc. + +A typical workflow would be composed of two major elements: + +- NoirJS +- Proving backend of choice's JavaScript package + + + +To install NoirJS, install Node.js if you have not already and run this in your JavaScript project: + +```bash +npm i @noir-lang/noir_js +``` + +## Proving backend + +Since Noir is backend agnostic, you can instantiate NoirJS without any backend (i.e. to execute a function). But for proving, you would have to instantiate NoirJS with any of the supported backends through their own `js` interface. + +### Barretenberg + +Aztec Labs maintains the `barretenberg` proving backend, which you can instantiate and make use of alongside NoirJS. It is also the default proving backend installed and used with Nargo, the Noir CLI tool. + +To install its JavaScript library, run this in your project: + +```bash +npm i @noir-lang/backend_barretenberg +``` + +For more details on how to instantiate and use the libraries, refer to the [Full Noir App Guide](./getting_started/01_tiny_noir_app.md) and [Reference](./reference/noir_js/classes/Noir.md) sections. diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/.nojekyll new file mode 100644 index 0000000000..e2ac6616ad --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 0000000000..5cbe9421b9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,185 @@ +# BarretenbergBackend + +## Implements + +- [`Backend`](../interfaces/Backend.md) + +## Constructors + +### new BarretenbergBackend(acirCircuit, options) + +```ts +new BarretenbergBackend(acirCircuit, options): BarretenbergBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergBackend`](BarretenbergBackend.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`destroy`](../interfaces/Backend.md#destroy) + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateFinalProof`](../interfaces/Backend.md#generatefinalproof) + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(witness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `witness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateIntermediateProof`](../interfaces/Backend.md#generateintermediateproof) + +#### Example + +```typescript +const intermediateProof = await backend.generateIntermediateProof(witness); +``` + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`generateIntermediateProofArtifacts`](../interfaces/Backend.md#generateintermediateproofartifacts) + +#### Example + +```typescript +const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`verifyFinalProof`](../interfaces/Backend.md#verifyfinalproof) + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Implementation of + +[`Backend`](../interfaces/Backend.md).[`verifyIntermediateProof`](../interfaces/Backend.md#verifyintermediateproof) + +#### Example + +```typescript +const isValidIntermediate = await backend.verifyIntermediateProof(proof); +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/index.md new file mode 100644 index 0000000000..93b248b0f6 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/index.md @@ -0,0 +1,45 @@ +# Backend Barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | + +### Interfaces + +| Interface | Description | +| :------ | :------ | +| [Backend](interfaces/Backend.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | + +## Functions + +### flattenPublicInputs() + +```ts +flattenPublicInputs(publicInputs): string[] +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `publicInputs` | `WitnessMap` | + +#### Returns + +`string`[] + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/interfaces/Backend.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/interfaces/Backend.md new file mode 100644 index 0000000000..3eb9645c8d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/interfaces/Backend.md @@ -0,0 +1,132 @@ +# Backend + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the backend + +*** + +### generateFinalProof() + +```ts +generateFinalProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a final proof (not meant to be verified in another circuit) + +*** + +### generateIntermediateProof() + +```ts +generateIntermediateProof(decompressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `decompressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates an intermediate proof (meant to be verified in another circuit) + +*** + +### generateIntermediateProofArtifacts() + +```ts +generateIntermediateProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | +| `numOfPublicInputs` | `number` | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Retrieves the artifacts from a proof in the Field format + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies a final proof + +*** + +### verifyIntermediateProof() + +```ts +verifyIntermediateProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies an intermediate proof + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 0000000000..266ade75d1 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,19 @@ +# BackendOptions + +```ts +type BackendOptions: object; +``` + +## Description + +An options object, currently only used to specify the number of threads to use. + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `threads` | `number` | **Description**

Number of threads | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md new file mode 100644 index 0000000000..34e0dd0420 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

ABI representation of the circuit | +| `bytecode` | `string` | **Description**

The bytecode of the circuit | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md new file mode 100644 index 0000000000..3eb360a78f --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md @@ -0,0 +1,20 @@ +# ProofData + +```ts +type ProofData: object; +``` + +## Description + +The representation of a proof + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | +| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 0000000000..04e662c845 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"}]},{"type":"category","label":"Interfaces","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/interfaces/Backend","label":"Backend"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/backend_barretenberg/type-aliases/ProofData","label":"ProofData"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/.nojekyll b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/.nojekyll new file mode 100644 index 0000000000..e2ac6616ad --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/classes/Noir.md new file mode 100644 index 0000000000..e54116fb1d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/classes/Noir.md @@ -0,0 +1,131 @@ +# Noir + +## Constructors + +### new Noir(circuit, backend) + +```ts +new Noir(circuit, backend?): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | [`CompiledCircuit`](../type-aliases/CompiledCircuit.md) | +| `backend`? | `Backend` | + +#### Returns + +[`Noir`](Noir.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Description + +Destroys the underlying backend instance. + +#### Example + +```typescript +await noir.destroy(); +``` + +*** + +### execute() + +```ts +execute(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Allows to execute a circuit to get its witness and return value. + +#### Example + +```typescript +async execute(inputs) +``` + +*** + +### generateFinalProof() + +```ts +generateFinalProof(inputs): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | [`InputMap`](../type-aliases/InputMap.md) | + +#### Returns + +`Promise`\<[`ProofData`](../type-aliases/ProofData.md)\> + +#### Description + +Generates a witness and a proof given an object as input. + +#### Example + +```typescript +async generateFinalproof(input) +``` + +*** + +### verifyFinalProof() + +```ts +verifyFinalProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | [`ProofData`](../type-aliases/ProofData.md) | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Instantiates the verification key and verifies a proof. + +#### Example + +```typescript +async verifyFinalProof(proof) +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/and.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/and.md new file mode 100644 index 0000000000..c783283e39 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/blake2s256.md new file mode 100644 index 0000000000..7882d0da8d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 0000000000..0ba5783f0d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,29 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. +Verifies a ECDSA signature over the secp256k1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 0000000000..0b20ff6895 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/keccak256.md new file mode 100644 index 0000000000..d10f155ce8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/sha256.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/sha256.md new file mode 100644 index 0000000000..6ba4ecac02 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/xor.md new file mode 100644 index 0000000000..8d762b895d --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/index.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/index.md new file mode 100644 index 0000000000..348453c005 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/index.md @@ -0,0 +1,37 @@ +# Noir JS + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [CompiledCircuit](type-aliases/CompiledCircuit.md) | - | +| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | +| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | +| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | +| [InputMap](type-aliases/InputMap.md) | - | +| [ProofData](type-aliases/ProofData.md) | - | +| [WitnessMap](type-aliases/WitnessMap.md) | - | + +### Functions + +| Function | Description | +| :------ | :------ | +| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | +| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | +| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Calculates the Blake2s256 hash of the input bytes and represents these as a single field element. | +| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | +| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | +| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | +| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md new file mode 100644 index 0000000000..34e0dd0420 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md @@ -0,0 +1,20 @@ +# CompiledCircuit + +```ts +type CompiledCircuit: object; +``` + +## Description + +The representation of a compiled circuit + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `abi` | `Abi` | **Description**

ABI representation of the circuit | +| `bytecode` | `string` | **Description**

The bytecode of the circuit | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 0000000000..812b8b1648 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# ForeignCallHandler + +```ts +type ForeignCallHandler: (name, inputs) => Promise; +``` + +A callback which performs an foreign call and returns the response. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | The identifier for the type of foreign call being performed. | +| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | + +## Returns + +`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> + +outputs - An array of hex encoded outputs containing the results of the foreign call. + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 0000000000..dd95809186 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# ForeignCallInput + +```ts +type ForeignCallInput: string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 0000000000..b71fb78a94 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# ForeignCallOutput + +```ts +type ForeignCallOutput: string | string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/InputMap.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/InputMap.md new file mode 100644 index 0000000000..c714e999d9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/InputMap.md @@ -0,0 +1,13 @@ +# InputMap + +```ts +type InputMap: object; +``` + +## Index signature + + \[`key`: `string`\]: `InputValue` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ProofData.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ProofData.md new file mode 100644 index 0000000000..3eb360a78f --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/ProofData.md @@ -0,0 +1,20 @@ +# ProofData + +```ts +type ProofData: object; +``` + +## Description + +The representation of a proof + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `proof` | `Uint8Array` | **Description**

An byte array representing the proof | +| `publicInputs` | `WitnessMap` | **Description**

Public inputs of a proof | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 0000000000..258c46f9d0 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/typedoc-sidebar.cjs new file mode 100644 index 0000000000..077ebeb133 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/noir_js/reference/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"noir_js/reference/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/CompiledCircuit","label":"CompiledCircuit"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/InputMap","label":"InputMap"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/ProofData","label":"ProofData"},{"type":"doc","id":"noir_js/reference/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"noir_js/reference/noir_js/functions/and","label":"and"},{"type":"doc","id":"noir_js/reference/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"noir_js/reference/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"noir_js/reference/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md new file mode 100644 index 0000000000..1dfabfe8f2 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md @@ -0,0 +1,46 @@ +--- +title: Black Box Functions +description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. +keywords: [noir, black box functions] +--- + +Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. + +:::warning + +It is likely that not all backends will support a particular black box function. + +::: + +Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. + +Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: + +```rust +#[foreign(sha256)] +fn sha256(_input : [u8; N]) -> [u8; 32] {} +``` + +## Function list + +Here is a list of the current black box functions that are supported by UltraPlonk: + +- AES +- [SHA256](./cryptographic_primitives/hashes#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr) +- [Blake2s](./cryptographic_primitives/hashes#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) +- [Compute merkle root](./merkle_trees#compute_merkle_root) +- AND +- XOR +- RANGE +- [Keccak256](./cryptographic_primitives/hashes#keccak256) +- [Recursive proof verification](./recursion) + +Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. + +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives.md similarity index 100% rename from docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives.md rename to docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives.md diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/00_hashes.mdx new file mode 100644 index 0000000000..7674519668 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/00_hashes.mdx @@ -0,0 +1,167 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s, pedersen, mimc_bn254 and mimc +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## sha256 + +Given an array of bytes, returns the resulting sha256 hash. + +```rust +fn sha256(_input : [u8]) -> [u8; 32] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::sha256(x); +} +``` + + + +## blake2s + +Given an array of bytes, returns an array with the Blake2 hash + +```rust +fn blake2s(_input : [u8]) -> [u8; 32] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake2s(x); +} +``` + + + +## pedersen_hash + +Given an array of Fields, returns the Pedersen hash. + +```rust +fn pedersen_hash(_input : [Field]) -> Field +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::pedersen_hash(x); +} +``` + + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust +fn pedersen_commitment(_input : [Field]) -> [Field; 2] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let commitment = std::hash::pedersen_commitment(x); +} +``` + + + +## keccak256 + +Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes +(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes +of the input. + +```rust +fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] +``` + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let message_size = 4; + let hash = std::hash::keccak256(x, message_size); +} +``` + + + +## poseidon + +Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify +how many inputs are there to your Poseidon function. + +```rust +// example for hash_1, hash_2 accepts an array of length 2, etc +fn hash_1(input: [Field; 1]) -> Field +``` + +example: + +```rust +fn main() +{ + let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); + assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); +} +``` + +## mimc_bn254 and mimc + +`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by +providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if +you're willing to input your own constants: + +```rust +fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field +``` + +otherwise, use the `mimc_bn254` method: + +```rust +fn mimc_bn254(array: [Field; N]) -> Field +``` + +example: + +```rust + +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::mimc::mimc_bn254(x); +} +``` + +## hash_to_field + +```rust +fn hash_to_field(_input : [Field; N]) -> Field {} +``` + +Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return +a value which can be represented as a `Field`. + + diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/01_scalar.mdx new file mode 100644 index 0000000000..c7eed820a8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/01_scalar.mdx @@ -0,0 +1,27 @@ +--- +title: Scalar multiplication +description: See how you can perform scalar multiplications over a fixed base in Noir +keywords: [cryptographic primitives, Noir project, scalar multiplication] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## scalar_mul::fixed_base_embedded_curve + +Performs scalar multiplication over the embedded curve whose coordinates are defined by the +configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. + +```rust +fn fixed_base_embedded_curve(_input : Field) -> [Field; 2] +``` + +example + +```rust +fn main(x : Field) { + let scal = std::scalar_mul::fixed_base_embedded_curve(x); + std::println(scal); +} +``` + + diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/02_schnorr.mdx new file mode 100644 index 0000000000..c184ce2812 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/02_schnorr.mdx @@ -0,0 +1,37 @@ +--- +title: Schnorr Signatures +description: Learn how you can verify Schnorr signatures using Noir +keywords: [cryptographic primitives, Noir project, schnorr, signatures] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## schnorr::verify_signature + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). + +```rust +fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool +``` + +where `_signature` can be generated like so using the npm package +[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) + +```js +const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); +const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); + +... + +const barretenberg = await BarretenbergWasm.new(); +const schnorr = new Schnorr(barretenberg); +const pubKey = schnorr.computePublicKey(privateKey); +const message = ... +const signature = Array.from( + schnorr.constructSignature(hash, privateKey).toBuffer() +); + +... +``` + + diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx new file mode 100644 index 0000000000..72bce98482 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx @@ -0,0 +1,45 @@ +--- +title: ECDSA Signature Verification +description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves +keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. + +## ecdsa_secp256k1::verify_signature + +Verifier for ECDSA Secp256k1 signatures + +```rust +fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool +``` + +example: + +```rust +fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { + let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} +``` + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures + +```rust +fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool +``` + +example: + +```rust +fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { + let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} +``` + + diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/04_ec_primitives.md similarity index 100% rename from docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/04_ec_primitives.md rename to docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/04_ec_primitives.md diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/05_eddsa.mdx new file mode 100644 index 0000000000..9a5beb55ee --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/standard_library/cryptographic_primitives/05_eddsa.mdx @@ -0,0 +1,17 @@ +--- +title: EdDSA Verification +description: Learn about the cryptographic primitives regarding EdDSA +keywords: [cryptographic primitives, Noir project, eddsa, signatures] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## eddsa::eddsa_poseidon_verify + +Verifier for EdDSA signatures + +```rust +fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool +``` + + diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/logging.md b/docs/versioned_docs/version-v0.19.4/standard_library/logging.md new file mode 100644 index 0000000000..7e2fd9b9af --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/standard_library/logging.md @@ -0,0 +1,62 @@ +--- +title: Logging +description: + Learn how to use the println statement for debugging in Noir with this tutorial. Understand the + basics of logging in Noir and how to implement it in your code. +keywords: + [ + noir logging, + println statement, + debugging in noir, + noir std library, + logging tutorial, + basic logging in noir, + noir logging implementation, + noir debugging techniques, + rust, + ] +--- + +The standard library provides a familiar `println` statement you can use. Despite being a limited +implementation of rust's `println!` macro, this construct can be useful for debugging. + +You can print the output of println statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are println statements in your tests). + +It is recommended to use `nargo execute` if you want to debug failing constrains with `println` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). `println` will not work for failed constraints caught at compile time. + +The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: + +```rust +use dep::std; + +struct Person { + age : Field, + height : Field, +} + +fn main(age : Field, height : Field) { + let person = Person { age : age, height : height }; + std::println(person); + std::println(age + height); + std::println("Hello world!"); +} + +``` + +You can print multiple different types in the same statement and string as well as a new "fmtstr" type. A `fmtstr` can be specified in the same way as a normal string it just should be prepended with an "f" character: + +```rust + let fmt_str = f"i: {i}, j: {j}"; + std::println(fmt_str); + + let s = myStruct { y: x, x: y }; + std::println(s); + + std::println(f"i: {i}, s: {s}"); + + std::println(x); + std::println([x, y]); + + let foo = fooStruct { my_struct: s, foo: 15 }; + std::println(f"s: {s}, foo: {foo}"); +``` diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.19.4/standard_library/merkle_trees.md new file mode 100644 index 0000000000..dc383a1426 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/standard_library/merkle_trees.md @@ -0,0 +1,58 @@ +--- +title: Merkle Trees +description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. +keywords: + [ + Merkle trees in Noir, + Noir programming language, + check membership, + computing root from leaf, + Noir Merkle tree implementation, + Merkle tree tutorial, + Merkle tree code examples, + Noir libraries, + pedersen hash., + ] +--- + +## compute_merkle_root + +Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen_hash). + +```rust +fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field +``` + +example: + +```rust +/** + // these values are for this example only + index = "0" + priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" + secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" + note_hash_path = [ + "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", + "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", + "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" + ] + */ +fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { + + let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); + let pubkey_x = pubkey[0]; + let pubkey_y = pubkey[1]; + let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); + + let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); + std::println(root); +} +``` + +To check merkle tree membership: + +1. Include a merkle root as a program input. +2. Compute the merkle root of a given leaf, index and hash path. +3. Assert the merkle roots are equal. + +For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/options.md b/docs/versioned_docs/version-v0.19.4/standard_library/options.md new file mode 100644 index 0000000000..3d3139fb98 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/standard_library/options.md @@ -0,0 +1,99 @@ +--- +title: Option Type +--- + +The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. + +```rust +struct Option { + None, + Some(T), +} +``` + +You can import the Option type into your Noir program like so: + +```rust +use dep::std::option::Option; + +fn main() { + let none = Option::none(); + let some = Option::some(3); +} +``` + +See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. + +## Methods + +### none + +Constructs a none value. + +### some + +Constructs a some wrapper around a given value. + +### is_none + +Returns true if the Option is None. + +### is_some + +Returns true of the Option is Some. + +### unwrap + +Asserts `self.is_some()` and returns the wrapped value. + +### unwrap_unchecked + +Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. + +### unwrap_or + +Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. + +### unwrap_or_else + +Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. + +### map + +If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. + +### map_or + +If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. + +### map_or_else + +If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. + +### and + +Returns None if self is None. Otherwise, this returns `other`. + +### and_then + +If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. + +### or + +If self is Some, return self. Otherwise, return `other`. + +### or_else + +If self is Some, return self. Otherwise, return `default()`. + +### xor + +If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. + +### filter + +Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. + +### flatten + +Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md b/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md new file mode 100644 index 0000000000..ff4c63acaa --- /dev/null +++ b/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md @@ -0,0 +1,96 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] +--- + +Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. + +The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. + +```rust +#[foreign(verify_proof)] +fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} +``` + +:::info + +This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. + +::: + +## Aggregation Object + +The purpose of the input aggregation object is a little less clear though (and the output aggregation object that is returned from the `std::verify_proof` method). Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points (thus completing the recursive verification). + +So for example in this circuit: + +```rust +use dep::std; + +fn main( + verification_key : [Field; 114], + proof : [Field; 94], + public_inputs : [Field; 1], + key_hash : Field, + input_aggregation_object : [Field; 16], + proof_b : [Field; 94], +) -> pub [Field; 16] { + let output_aggregation_object_a = std::verify_proof( + verification_key, + proof, + public_inputs, + key_hash, + input_aggregation_object + ); + + let output_aggregation_object = std::verify_proof( + verification_key, + proof_b, + public_inputs, + key_hash, + output_aggregation_object_a + ); + + let mut output = [0; 16]; + for i in 0..16 { + output[i] = output_aggregation_object[i]; + } + output +} +``` + +In this example we have a circuit, that generates proofs A and B, that is being verified in circuit C. Assuming that the proof being passed in is not already a recursive proof, the `input_aggregation_object` will be all zeros. It will then generate an `output_aggregation_object`. This blob of data then becomes the `input_aggregation_object` of the next recursive aggregation we wish to compute. We can see here as the same public inputs, verification key, and key hash are used that we are verifying two proofs generated from the same circuit in this single circuit. `std::verify_proof` returns a `[Field]` because the size of an aggregation object is proof system dependent--in barretenberg, aggregation objects are two G1 points, while in Halo2, the aggregation object is a list of G1 points that is log the circuit size. So for the final step we convert the slice into an array of size 16 because we are generating proofs using UltraPlonk. + +## Parameters + +### `verification_key` + +The verification key for the zk program that is being verified. + +### `proof` + +The proof for the zk program that is being verified. + +### `public_inputs` + +These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. + +### `key_hash` + +A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. + +### `input_aggregation_object` + +An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. + +## Return value + +### `output_aggregation_object` + +This is the result of a recursive aggregation and is what will be fed into the next verifier. +The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. + +## Example + +You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/zeroed.md b/docs/versioned_docs/version-v0.19.4/standard_library/zeroed.md similarity index 100% rename from docs/versioned_docs/version-v0.7.1/standard_library/zeroed.md rename to docs/versioned_docs/version-v0.19.4/standard_library/zeroed.md diff --git a/docs/versioned_docs/version-v0.6.0/examples/merkle-proof.md b/docs/versioned_docs/version-v0.6.0/examples/merkle-proof.md deleted file mode 100644 index 4696b4a142..0000000000 --- a/docs/versioned_docs/version-v0.6.0/examples/merkle-proof.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[view an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md deleted file mode 100644 index 432884b709..0000000000 --- a/docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,283 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [TypeScript](../typescript). - -### UltraPlonk - -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Install via Nix](#option-3-install-via-nix) -- [Option 4: Compile from Source](#option-4-compile-from-source) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -v 0.6.0 -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Windows (PowerShell) - -Open PowerShell as Administrator and run: - -```powershell -mkdir -f -p "$env:USERPROFILE\.nargo\bin\"; ` -Invoke-RestMethod -Method Get -Uri https://github.com/noir-lang/noir/releases/download/v0.4.1/nargo-x86_64-pc-windows-msvc.zip -Outfile "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip"; ` -Expand-Archive -Path "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip" -DestinationPath "$env:USERPROFILE\.nargo\bin\"; ` -$Reg = "Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment"; ` -$OldPath = (Get-ItemProperty -Path "$Reg" -Name PATH).Path; ` -$NewPath = $OldPath + ’;’ + "$env:USERPROFILE\.nargo\bin\"; ` -Set-ItemProperty -Path "$Reg" -Name PATH –Value "$NewPath"; ` -$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Install via Nix - -Due to the large number of native dependencies, Noir projects can be installed via [Nix](https://nixos.org/). - -#### Installing Nix - -For the best experience, please follow these instructions to setup Nix: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -#### Install Nargo into your Nix profile - -1. Use `nix profile` to install Nargo - -```sh -nix profile install github:noir-lang/noir -``` - -### Option 4: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` -> Replacing `noir` with whichever repository you cloned. - -3. You should see a __direnv error__ because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `flake.nix`, which is 1.66.0 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git -[rust]: https://www.rust-lang.org/tools/install -[noir vs code extension]: - https://marketplace.visualstudio.com/items?itemName=noir-lang.noir-programming-language-syntax-highlighter -[homebrew]: https://brew.sh/ -[cmake]: https://cmake.org/install/ -[llvm]: https://llvm.org/docs/GettingStarted.html -[openmp]: https://openmp.llvm.org/ -[barretenberg]: https://github.com/AztecProtocol/barretenberg diff --git a/docs/versioned_docs/version-v0.6.0/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.6.0/getting_started/01_hello_world.md deleted file mode 100644 index 0f21ad4556..0000000000 --- a/docs/versioned_docs/version-v0.6.0/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program with your preferred proof name, for example `p`: - -```sh -nargo prove p -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`p.proof`. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof of name `p` by running: - -```sh -nargo verify p -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](breakdown), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.6.0/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.6.0/getting_started/02_breakdown.md deleted file mode 100644 index 5f4f00a3f3..0000000000 --- a/docs/versioned_docs/version-v0.6.0/getting_started/02_breakdown.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -_Prover.toml_ is used for specifying the input values for executing and proving the program. -Optionally you may specify expected output values for prove-time checking as well. - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -_Nargo.toml_ contains the environmental options of your project. - -_proofs_ and _contract_ directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - constrain x != y; -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `constrain` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove my_proof` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `constrain x != y`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory and names the proof - file _my_proof_. Opening this file will display the proof in hex format. - -## Verifying a Proof - -When the command `nargo verify my_proof` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a file called _my_proof_ - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). diff --git a/docs/versioned_docs/version-v0.6.0/index.md b/docs/versioned_docs/version-v0.6.0/index.md deleted file mode 100644 index f4706182ff..0000000000 --- a/docs/versioned_docs/version-v0.6.0/index.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -This version of the book is being released with the public alpha. There will be a lot of features -that are missing in this version, however the syntax and the feel of the language will mostly be -completed. - -## What is Noir? - -Noir is a domain specific language for creating and verifying proofs. It's design choices are -influenced heavily by Rust. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). - -This in itself brings up a few challenges -within the design process, but allows one to decouple the programming language completely from the -backend. This is similar in theory to LLVM. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Ethereum Developers - -Noir currently includes a command to publish a contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the `contract` command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/00_data_types.md b/docs/versioned_docs/version-v0.6.0/language_concepts/00_data_types.md deleted file mode 100644 index 3a711fc892..0000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/00_data_types.md +++ /dev/null @@ -1,301 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - field type, - integer types, - boolean type, - array type, - tuple type, - struct type, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Primitive Types - -A primitive type represents a single value. They can be private or public. - -### Fields - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -### Integers - -An integer type is a range constrained field type. The Noir frontend currently supports unsigned, -arbitrary-sized integer types. - -An integer type is specified first with the letter `u`, indicating its unsigned nature, followed by -its length in bits (e.g. `32`). For example, a `u32` variable can store a value in the range of -$\\([0,2^{32}-1]\\)$: - -```rust -fn main(x : Field, y : u32) { - let z = x as u32 + y; -} -``` - -`x`, `y` and `z` are all private values in this example. However, `x` is a field while `y` and `z` -are unsigned 32-bit integers. If `y` or `z` exceeds the range $\\([0,2^{32}-1]\\)$, proofs created -will be rejected by the verifier. - -> **Note:** The default backend supports both even (e.g. `u16`, `u48`) and odd (e.g. `u5`, `u3`) -> sized integer types. - -### Booleans - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `constrain` -statements. More about conditionals is covered in the [Control Flow](./control_flow) and -[Constrain Statement](./constrain) sections. - -### Strings - -The string type is a fixed length value defined with `str`. - -You can use strings in `constrain` statements, `assert()` functions or print them with -`std::println()`. - -```rust -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -## Compound Types - -A compound type groups together multiple values into one type. Elements within a compound type can -be private or public. - -### Arrays - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -#### Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -### Tuples - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` - -### Structs - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. - -:::note -You can use Structs as inputs to the `main` function, but you can't output them -::: diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.6.0/language_concepts/01_functions.md deleted file mode 100644 index c4bc0545a1..0000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/01_functions.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : pub Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : pub Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - constrain s.sum() == 42; -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -constrain MyStruct::sum(s) == 42 -``` diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.6.0/language_concepts/02_control_flow.md deleted file mode 100644 index 29108dd263..0000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/02_control_flow.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditonal to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - constrain x == 5; -} -constrain x == 2; -``` diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md deleted file mode 100644 index d08df2094a..0000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -constrain flag == 1; - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -constrain flag == 0; -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.6.0/language_concepts/04_assert.md deleted file mode 100644 index a25a946123..0000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/04_assert.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. - -### Example - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -The above snippet compiles because `==` is a predicate operation. Conversely, the following will not -compile: - -```rust -// INCORRECT - -fn main(x : Field, y : Field) { - assert(x + y); -} -``` - -> The rationale behind this not compiling is due to ambiguity. It is not clear if the above should -> equate to `x + y == 0` or if it should check the truthiness of the result. diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/05_constrain.md b/docs/versioned_docs/version-v0.6.0/language_concepts/05_constrain.md deleted file mode 100644 index 9ba1e260e8..0000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/05_constrain.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Constrain Statements -description: - Learn about the constrain keyword in Noir, which can be used to explicitly constrain the predicate - or comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: - [Noir programming language, constrain statement, predicate expression, comparison expression] ---- - -:::danger - -In versions >=0.5.0 use the [`assert`](./04_assert.md) syntax. The `constrain` statement will be -maintained for some time for backwards compatibility but will be deprecated in the future. - -::: - -Noir includes a special keyword `constrain` which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. - -### Constrain statement example - -```rust -fn main(x : Field, y : Field) { - constrain x == y; -} -``` - -The above snippet compiles because `==` is a predicate operation. Conversely, the following will not -compile: - -```rust -fn main(x : Field, y : Field) { - constrain x + y; -} -``` - -> The rationale behind this not compiling is due to ambiguity. It is not clear if the above should -> equate to `x + y == 0` or if it should check the truthiness of the result. diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.6.0/language_concepts/06_generics.md deleted file mode 100644 index 4d6c01fd79..0000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/06_generics.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Generics -description: - Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -# Generics - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: comptime Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - constrain first.limbs != second.limbs; - first - - fn second(first: BigInt, second: Self) -> Self { - constrain first.limbs != second.limbs; - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - constrain array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - constrain array_eq(array, array, MyStruct::eq); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.6.0/language_concepts/07_mutability.md deleted file mode 100644 index c8ccb4f8b9..0000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/07_mutability.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -# Mutability - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a } -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime values - -Comptime value are values that are known at compile-time. This is different to a witness -which changes per proof. If a comptime value that is being used in your program is changed, then your -circuit will also change. - -Below we show how to declare a comptime value: - -```rust -fn main() { - let a: comptime Field = 5; - - // `comptime Field` can also be inferred: - let a = 5; -} -``` - -Note that variables declared as mutable may not be comptime: - -```rust -fn main() { - // error: Cannot mark a comptime type as mutable - let mut a: comptime Field = 5; - - // a inferred as a private Field here - let mut a = 5; -} -``` - -## Globals - -Noir also supports global variables. However, they must be compile-time variables. If `comptime` is -not explicitly written in the type annotation the compiler will implicitly specify the declaration -as compile-time. They can then be used like any other compile-time variable inside functions. The -global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: comptime Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - constrain res == y[0]; - - let res2 = x * mysubmodule::N; - constrain res != res2; -} - -mod mysubmodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> comptime Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/08_comments.md b/docs/versioned_docs/version-v0.6.0/language_concepts/08_comments.md deleted file mode 100644 index 5b1d9fa38f..0000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/08_comments.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir doesn't have multi-line comments, but you can emulate them via using `//` on each line - -```rust -// This is a multi line -// comment, that is ignored by -// the compiler -``` diff --git a/docs/versioned_docs/version-v0.6.0/language_concepts/09_distinct.md b/docs/versioned_docs/version-v0.6.0/language_concepts/09_distinct.md deleted file mode 100644 index 03759d4bb4..0000000000 --- a/docs/versioned_docs/version-v0.6.0/language_concepts/09_distinct.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Distinct Witnesses ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `disctinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/docs/versioned_docs/version-v0.6.0/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.6.0/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 34f28a7114..0000000000 --- a/docs/versioned_docs/version-v0.6.0/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Crates and Packages -description: - Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in one of two forms: a binary crate or a library crate. - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/docs/versioned_docs/version-v0.6.0/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.6.0/modules_packages_crates/dependencies.md deleted file mode 100644 index f3b40eb849..0000000000 --- a/docs/versioned_docs/version-v0.6.0/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Managing Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.2.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -``` -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── liba - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -libA = { path = "../liba" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: - -```rust -use dep::ecrecover; -use dep::libA; -``` - -You can also import only the specific parts of dependency that you want to use. For example, -demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you -can import just the `Point` and the `Curve` that you want to use. - -```rust -use dep::std::ec::tecurve::affine::Curve; -use dep::std::ec::tecurve::affine::Point; -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- BigInt -- "`ecrecover`" -- sparse merkle tree verifier diff --git a/docs/versioned_docs/version-v0.6.0/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.6.0/modules_packages_crates/modules.md deleted file mode 100644 index e429b33651..0000000000 --- a/docs/versioned_docs/version-v0.6.0/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Understanding Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -# Modules - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organise files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree -All modules are accessible from the ``crate::`` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` -In the above snippet, if ``bar`` would like to use functions in ``foo``, it can do so by ``use crate::foo::function_name``. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/docs/versioned_docs/version-v0.6.0/nargo/01_commands.md b/docs/versioned_docs/version-v0.6.0/nargo/01_commands.md deleted file mode 100644 index f9d9ddb77f..0000000000 --- a/docs/versioned_docs/version-v0.6.0/nargo/01_commands.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -``` -Options: - -s, --show-ssa Emit debug information for the intermediate SSA IR - -d, --deny-warnings Quit execution when warnings are emitted - --show-output Display output of `println` statements during tests - -h, --help Print help -``` - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -- `` - The subcommand whose help message to display - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -## `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -## `nargo compile ` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -_Arguments_ - -- `` - The name of the circuit file - -_Options_ - -- `-c, --contracts` - Compile each contract function used within the program - -## `nargo new [path]` - -Creates a new Noir project. - -_Arguments_ - -- `` - Name of the package -- `[path]` - The path to save the new project - -## `nargo execute [witness_name]` - -Runs the Noir program and prints its return value. - -_Arguments_ - -- `[witness_name]` - The name of the witness - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `witness-name` argument. A -`.tr` file will then be saved in the `build` folder. - -> **Info:** The `.tr` file is the witness file. The witness file can be considered as program inputs -> parsed for your program's ACIR. -> -> This file can be passed along with circuit's ACIR into a TypeScript project for proving and -> verification. See the [TypeScript](../typescript#proving-and-verifying-externally-compiled-files) -> section to learn more. - -## `nargo prove ` - -Creates a proof for the program. - -_Arguments_ - -- `` - The name of the proof - -_Options_ - -- `-v, --verify` - Verify proof after proving - -## `nargo verify ` - -Given a proof and a program, verify whether the proof is valid. - -_Arguments_ - -- `` - The proof to verify - -## `nargo test ` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -See an example on the [testing page](./testing). - -_Arguments_ - -- `` - a pattern to indicate to only run tests with names containing the pattern - -## `nargo gates` - -Counts the occurrences of different gates in circuit - -## `nargo print-acir` - -Print a compiled circuit to stdout such that the ACIR can be inspected. diff --git a/docs/versioned_docs/version-v0.6.0/nargo/02_testing.md b/docs/versioned_docs/version-v0.6.0/nargo/02_testing.md deleted file mode 100644 index 73f91c72bf..0000000000 --- a/docs/versioned_docs/version-v0.6.0/nargo/02_testing.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - constrain add(2,2) == 4; - constrain add(0,1) == 1; - constrain add(1,0) == 1; -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -This is much faster compared to testing in Typescript but the only downside is that you can't -explicitly test that a certain set of inputs are invalid. i.e. you can't say that you want -add(2^64-1, 2^64-1) to fail. diff --git a/docs/versioned_docs/version-v0.6.0/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.6.0/nargo/03_solidity_verifier.md deleted file mode 100644 index 69a5607f1b..0000000000 --- a/docs/versioned_docs/version-v0.6.0/nargo/03_solidity_verifier.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do *not* currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/array_methods.md b/docs/versioned_docs/version-v0.6.0/standard_library/array_methods.md deleted file mode 100644 index 701590ccf5..0000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/array_methods.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -title: Array Methods -description: - Learn about the commonly used methods available for arrays in Noir, including len, sort, fold, - reduce, all, and any. -keywords: [rust, array, methods, len, sort, fold, reduce, all, any] ---- - -# Array - -For convenience, the STD provides some ready-to-use, common methods for arrays[^migrationnote]: - -## len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - constrain array.len() == 2; -} -``` - -## sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted = arr.sort(); - constrain sorted == [32, 42]; -} -``` - -## sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a < b); - constrain sorted_ascending == [32, 42]; // verifies - - let sorted_descending = arr.sort_via(|a, b| a > b); - constrain sorted_descending == [32, 42]; // does not verify -} -``` - -## map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2) // b is now [2, 4, 6] -``` - -## fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2,2,2,2,2] - let folded = arr.fold(0, |a, b| a + b); - constrain folded == 10; -} - -``` - -## reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2,2,2,2,2] - let reduced = arr.reduce(|a, b| a + b); - constrain reduced == 10; -} -``` - -## all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2,2,2,2,2] - let all = arr.all(|a| a == 2); - constrain all; -} -``` - -## any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2,2,2,2,5] - let any = arr.any(|a| a == 5); - constrain any; -} - -``` - -[^migrationnote]: - Migration Note: These methods were previously free functions, called via `std::array::len()`. - For the sake of ease of use and readability, these functions are now methods and the old syntax - for them is now deprecated. diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.6.0/standard_library/black_box_fns.md deleted file mode 100644 index 3063e71c14..0000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/black_box_fns.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen](./cryptographic_primitives/hashes#pedersen) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_secp256k1) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index c373f10ca6..0000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, blake2s, pedersen, mimc_bn254 and mimc -keywords: - [ - cryptographic primitives, - Noir project, - sha256, - blake2s, - pedersen, - mimc_bn254, - mimc, - hash - ] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::pedersen(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes (`[u8; 32]`). - -```rust -fn keccak256(_input : [u8; N]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::keccak256(x); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - constrain hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a; -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return a value which can be represented as a `Field`. - - diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index 62265cddb1..0000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: - See how you can perform scalar multiplications over a fixed base in Noir -keywords: - [ - cryptographic primitives, - Noir project, - scalar multiplication, - ] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## scalar_mul::fixed_base - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base(x); - std::println(scal); -} -``` - - diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index c2c6f3ae19..0000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> Field -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx deleted file mode 100644 index 88892712fb..0000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: ECDSA Verification -description: - Learn about the cryptographic primitives regarding ECDSA over the secp256k1 curve -keywords: - [ - cryptographic primitives, - Noir project, - ecdsa, - secp256k1, - signatures, - ] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> Field -``` - - diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/04_ec_primitives.md deleted file mode 100644 index 2d4ed0f8fa..0000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/04_ec_primitives.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/crates/nargo_cli/tests/test_data/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::Curve; -use dep::std::ec::tecurve::affine::Point; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/common/_blackbox.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/common/_blackbox.mdx deleted file mode 100644 index 9fe9b48fbf..0000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/common/_blackbox.mdx +++ /dev/null @@ -1,5 +0,0 @@ -:::info - -This is a black box function. Read [this section](../black_box_fns) to learn more about black box functions in Noir. - -::: \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md b/docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md deleted file mode 100644 index 7cea984610..0000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Field Methods -description: - Learn about common methods on Noir Field, including to_le_bits, to_le_bytes, to_le_radix, - to_be_radix, pow_32, etc, and see code examples. -keywords: - [ - Noir Field, - to_le_bits, - to_le_bytes, - to_le_radix, - to_be_radix, - pow_32, - Little Endian, - Big Endian, - Vector, - Exponent, - ] ---- - -After declaring a Field, you can use these common methods on it: - -## to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2 - let bits = field.to_le_bits(32); -} -``` - -## to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2 - let bits = field.to_be_bits(32); -} -``` - -## to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let bytes = field.to_le_bytes(4); -} -``` - -## to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let bytes = field.to_be_bytes(4); -} -``` - -## to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let radix = field.to_le_radix(256, 4); -} -``` - -## to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let radix = field.to_be_radix(256, 4); -} -``` - -## pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - constrain pow == 16; -} -``` - -## sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/logging.md b/docs/versioned_docs/version-v0.6.0/standard_library/logging.md deleted file mode 100644 index 649d35a3f0..0000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/logging.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -# Logging - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -The `println` statement only works for fields, integers and arrays (including strings). - -```rust -use dep::std; - -fn main(string: pub str<5>) { - let x = 5; - std::println(x) -} - -``` - -To view the output of the `println` statement you need to set the `--show-output` flag. - -``` -$ nargo prove --help -Create proof for this program. The proof is returned as a hex encoded string - -Usage: nargo prove [OPTIONS] [PROOF_NAME] [CIRCUIT_NAME] - -Arguments: - [PROOF_NAME] The name of the proof - [CIRCUIT_NAME] The name of the circuit build files (ACIR, proving and verification keys) - -Options: - -v, --verify Verify proof after proving - -s, --show-ssa Emit debug information for the intermediate SSA IR - -d, --deny-warnings Quit execution when warnings are emitted - --show-output Display output of `println` statements during tests - -h, --help Print help -``` diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.6.0/standard_library/merkle_trees.md deleted file mode 100644 index fc8909a479..0000000000 --- a/docs/versioned_docs/version-v0.6.0/standard_library/merkle_trees.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Merkle Trees -description: - Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.6.0/typescript.md b/docs/versioned_docs/version-v0.6.0/typescript.md deleted file mode 100644 index fae002dfd2..0000000000 --- a/docs/versioned_docs/version-v0.6.0/typescript.md +++ /dev/null @@ -1,262 +0,0 @@ ---- -title: Working with TypeScript -description: - Learn how to interact with Noir programs using TypeScript. Follow this tutorial to compile your - program, specify inputs, initialize a prover & verifier, and prove and verify your program. -keywords: [TypeScript, Noir, tutorial, compile, inputs, prover, verifier, proof] ---- - -Interactions with Noir programs can also be performed in TypeScript, which can come in handy when -writing tests or when working in TypeScript-based projects like [Hardhat](https://hardhat.org/). - -This guide is based on the [noir-starter](https://github.com/signorecello/noir-starter) example. -Please refer to it for an example implementation. - -:::note - -You may find unexpected errors working with some frameworks such as `vite`. This is due to the -nature of `wasm` files and the way Noir uses web workers. As we figure it out, we suggest using -[Create React App](https://create-react-app.dev/), or [Next.js](https://nextjs.org/) for a quick -start. - -::: - -## Setup - -We're assuming you're using ES6 for both browser (for example with React), or nodejs. - -Install [Yarn](https://yarnpkg.com/) or [Node.js](https://nodejs.org/en). Init a new project with -`npm init`. Install Noir dependencies in your project by running: - -```bash -npm i @noir-lang/noir_wasm@0.3.2-fa0e9cff github:noir-lang/barretenberg#39a1547875f941ef6640217a42d8f34972425c97 @noir-lang/aztec_backend@0.1.0-0c3b2f2 -``` - -:::note - -While Noir is in rapid development, some packages could interfere with others. For that reason, you -should use these specified versions. Let us know if for some reason you need to use other ones. - -::: - -As for the circuit, we will use the _Standard Noir Example_ and place it in the `src` folder. Feel -free to use any other, as long as you refactor the below examples accordingly. - -This standard example is a program that multiplies input `x` with input `y` and returns the result: - -```rust -// src/main.nr -fn main(x: u32, y: pub u32) -> pub u32 { - let z = x * y; - z -} -``` - -One valid scenario for proving could be `x = 3`, `y = 4` and `return = 12` - -## Imports - -We need some imports, for both the `noir_wasm` library (which will compile the circuit into `wasm` -executables) and `aztec_backend` which is the actual proving backend we will be using. - -We also need to tell the compiler where to find the `.nr` files, so we need to import -`initialiseResolver`. - -```ts -import initNoirWasm, { acir_read_bytes, compile } from '@noir-lang/noir_wasm'; -import initialiseAztecBackend from '@noir-lang/aztec_backend'; -import { initialiseResolver } from '@noir-lang/noir-source-resolver'; -``` - -## Compiling - -We'll go over the code line-by-line later: - -```ts -export const compileCircuit = async () => { - await initNoirWasm(); - - return await fetch(new URL('../src/main.nr', import.meta.url)) - .then(r => r.text()) - .then(code => { - initialiseResolver((id: any) => { - return code; - }); - }) - .then(() => { - try { - const compiled_noir = compile({}); - return compiled_noir; - } catch (e) { - console.log('Error while compiling:', e); - } - }); -}; -``` - -1. First we're calling `initNoirWasm`. This is required on the browser only. -2. We then pass an URL that points to our `main.nr` file, and call `.then` on it so we can get the - actual text of the source code -3. We call `initialiseResolver` returning the source code -4. Finally, we can call the `compile` function - -This function should return us the compiled circuit. - -:::note - -You can use as many files as you need, -[importing them as you would do with Nargo](./modules_packages_crates/dependencies), and you don't -need to set them up in the `src` folder. Just mind the following particularities about -`initialiseResolver`: - -1. The `compile` function expects a `main.nr` file as an entry point. If you need another one, just - pass it as a `entry_point` parameter to `compile`. Check the - [noir starter](https://github.com/signorecello/noir-starter) for an example on multiple files and - a non-default entry point. -2. `initialiseResolver` needs to be synchronous -3. Different frameworks use different ways of fetching files. It's beyond the scope of this guide to - explain why and how, but for reference, - [noir starter](https://github.com/signorecello/noir-starter) uses both Next.js and node.js for - testing. - -Quick tip: an easy way to deal with `initialiseResolver` is just to prepare a -`{fileName: "literally_the_code"}` object beforehand - -::: - -## ACIR - -Noir compiles to two properties: - -1. The ACIR, which is the intermediate language used by backends such as Barretenberg -2. The ABI, which tells you which inputs are to be read - -Let's write a little function that gets us both, initializes the backend, and returns the ACIR as -bytes: - -```ts -export const getAcir = async () => { - const { circuit, abi } = await compileCircuit(); - await initialiseAztecBackend(); - - let acir_bytes = new Uint8Array(Buffer.from(circuit, 'hex')); - return acir_read_bytes(acir_bytes); -}; -``` - -Calling `getAcir()` now should return us the ACIR of the circuit, ready to be used in proofs. - -## Initializing Prover & Verifier - -Prior to proving and verifying, the prover and verifier have to first be initialized by calling -`barretenberg`'s `setup_generic_prover_and_verifier` with your Noir program's ACIR: - -```ts -let [prover, verifier] = await setup_generic_prover_and_verifier(acir); -``` - -This is probably a good time to store this prover and verifier into your state like React Context, -Redux, or others. - -## Proving - -The Noir program can then be executed and proved by calling `barretenberg`'s `create_proof` -function: - -```ts -const proof = await create_proof(prover, acir, abi); -``` - -On the browser, this proof can fail as it requires heavy loads to be run on worker threads. Here's a -quick example of a worker: - -```ts -// worker.ts -onmessage = async event => { - try { - await initializeAztecBackend(); - const { acir, input } = event.data; - const [prover, verifier] = await setup_generic_prover_and_verifier(acir); - const proof = await create_proof(prover, acir, input); - postMessage(proof); - } catch (er) { - postMessage(er); - } finally { - close(); - } -}; -``` - -Which would be called like this, for example: - -```ts -// index.ts -const worker = new Worker(new URL('./worker.ts', import.meta.url)); -worker.onmessage = e => { - if (e.data instanceof Error) { - // oh no! - } else { - // yey! - } -}; -worker.postMessage({ acir, input: { x: 3, y: 4 } }); -``` - -## Verifying - -The `proof` obtained can be verified by calling `barretenberg`'s `verify_proof` function: - -```ts -// 1_mul.ts -const verified = await verify_proof(verifier, proof); -``` - -The function should return `true` if the entire process is working as intended, which can be -asserted if you are writing a test script: - -```ts -expect(verified).eq(true); -``` - -## Verifying with Smart Contract - -Alternatively, a verifier smart contract can be generated and used for verifying Noir proofs in -TypeScript as well. - -This could be useful if the Noir program is designed to be decentrally verified and/or make use of -decentralized states and logics that is handled at the smart contract level. - -To generate the verifier smart contract using typescript: - -```ts -// generator.ts -import { writeFileSync } from 'fs'; - -const sc = verifier.SmartContract(); -syncWriteFile('../contracts/plonk_vk.sol', sc); - -function syncWriteFile(filename: string, data: any) { - writeFileSync(join(__dirname, filename), data, { - flag: 'w', - }); -} -``` - -You can then verify a Noir proof using the verifier contract, for example using Hardhat: - -```ts -// verifier.ts -import { ethers } from 'hardhat'; -import { Contract, ContractFactory, utils } from 'ethers'; - -let Verifier: ContractFactory; -let verifierContract: Contract; - -before(async () => { - Verifier = await ethers.getContractFactory('TurboVerifier'); - verifierContract = await Verifier.deploy(); -}); - -// Verify proof -const sc_verified = await verifierContract.verify(proof); -``` diff --git a/docs/versioned_docs/version-v0.7.1/examples/merkle-proof.md b/docs/versioned_docs/version-v0.7.1/examples/merkle-proof.md deleted file mode 100644 index 4696b4a142..0000000000 --- a/docs/versioned_docs/version-v0.7.1/examples/merkle-proof.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[view an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md deleted file mode 100644 index fb86a966e7..0000000000 --- a/docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,284 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [TypeScript](../typescript). - -### UltraPlonk - -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Install via Nix](#option-3-install-via-nix) -- [Option 4: Compile from Source](#option-4-compile-from-source) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Windows (PowerShell) - -Open PowerShell as Administrator and run: - -```powershell -mkdir -f -p "$env:USERPROFILE\.nargo\bin\"; ` -Invoke-RestMethod -Method Get -Uri https://github.com/noir-lang/noir/releases/download/v0.4.1/nargo-x86_64-pc-windows-msvc.zip -Outfile "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip"; ` -Expand-Archive -Path "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip" -DestinationPath "$env:USERPROFILE\.nargo\bin\"; ` -$Reg = "Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment"; ` -$OldPath = (Get-ItemProperty -Path "$Reg" -Name PATH).Path; ` -$NewPath = $OldPath + ’;’ + "$env:USERPROFILE\.nargo\bin\"; ` -Set-ItemProperty -Path "$Reg" -Name PATH –Value "$NewPath"; ` -$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Install via Nix - -Due to the large number of native dependencies, Noir projects can be installed via [Nix](https://nixos.org/). - -#### Installing Nix - -For the best experience, please follow these instructions to setup Nix: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -#### Install Nargo into your Nix profile - -1. Use `nix profile` to install Nargo - -```sh -nix profile install github:noir-lang/noir -``` - -### Option 4: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `flake.nix`, which is 1.66.0 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git -[rust]: https://www.rust-lang.org/tools/install -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir -[homebrew]: https://brew.sh/ -[cmake]: https://cmake.org/install/ -[llvm]: https://llvm.org/docs/GettingStarted.html -[openmp]: https://openmp.llvm.org/ -[barretenberg]: https://github.com/AztecProtocol/barretenberg diff --git a/docs/versioned_docs/version-v0.7.1/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.7.1/getting_started/01_hello_world.md deleted file mode 100644 index 0f21ad4556..0000000000 --- a/docs/versioned_docs/version-v0.7.1/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program with your preferred proof name, for example `p`: - -```sh -nargo prove p -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`p.proof`. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof of name `p` by running: - -```sh -nargo verify p -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](breakdown), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.7.1/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.7.1/getting_started/02_breakdown.md deleted file mode 100644 index 64d04c4e06..0000000000 --- a/docs/versioned_docs/version-v0.7.1/getting_started/02_breakdown.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -_Nargo.toml_ contains the environmental options of your project. - -_proofs_ and _contract_ directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove my_proof` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory and names the proof - file _my_proof_. Opening this file will display the proof in hex format. - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates proof `p`: - -```bash -nargo prove p -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof `pp`: - -```bash -nargo prove -p OtherProver pp -``` - -## Verifying a Proof - -When the command `nargo verify my_proof` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a file called _my_proof_ - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. - -In the [next section](language_server), we will explain how to utilize the Noir Language Server. diff --git a/docs/versioned_docs/version-v0.7.1/getting_started/03_language_server.md b/docs/versioned_docs/version-v0.7.1/getting_started/03_language_server.md deleted file mode 100644 index e6f5dfc2fa..0000000000 --- a/docs/versioned_docs/version-v0.7.1/getting_started/03_language_server.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Language Server -description: - Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: - [Nargo, Language Server, LSP, VSCode, Visual Studio Code] ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -### Configuration - -* __Noir: Enable LSP__ - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -* __Noir: Nargo Flags__ - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -* __Noir: Nargo Path__ - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -* __Noir > Trace: Server__ - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.7.1/index.md b/docs/versioned_docs/version-v0.7.1/index.md deleted file mode 100644 index e56b24bccd..0000000000 --- a/docs/versioned_docs/version-v0.7.1/index.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -This version of the book is being released with the public alpha. There will be a lot of features -that are missing in this version, however the syntax and the feel of the language will mostly be -completed. - -## What is Noir? - -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. - -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Solidity Developers - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen -- HashToField - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/00_data_types.md b/docs/versioned_docs/version-v0.7.1/language_concepts/00_data_types.md deleted file mode 100644 index 6ac494ad40..0000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/00_data_types.md +++ /dev/null @@ -1,305 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - field type, - integer types, - boolean type, - array type, - tuple type, - struct type, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Primitive Types - -A primitive type represents a single value. They can be private or public. - -### Fields - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -### Integers - -An integer type is a range constrained field type. The Noir frontend currently supports unsigned, -arbitrary-sized integer types. - -An integer type is specified first with the letter `u`, indicating its unsigned nature, followed by -its length in bits (e.g. `32`). For example, a `u32` variable can store a value in the range of -$\\([0,2^{32}-1]\\)$: - -```rust -fn main(x : Field, y : u32) { - let z = x as u32 + y; -} -``` - -`x`, `y` and `z` are all private values in this example. However, `x` is a field while `y` and `z` -are unsigned 32-bit integers. If `y` or `z` exceeds the range $\\([0,2^{32}-1]\\)$, proofs created -will be rejected by the verifier. - -> **Note:** The default backend supports both even (e.g. `u16`, `u48`) and odd (e.g. `u5`, `u3`) -> sized integer types. - -### Booleans - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](./control_flow) and -[Assert Function](./assert) sections. - -### Strings - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`std::println()`. - -```rust -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -## Compound Types - -A compound type groups together multiple values into one type. Elements within a compound type can -be private or public. - -### Arrays - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -#### Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -### Tuples - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` - -### Structs - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. - -:::note -You can use Structs as inputs to the `main` function, but you can't output them -::: - -### BigInt - -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.7.1/language_concepts/01_functions.md deleted file mode 100644 index 54c618599d..0000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/01_functions.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : pub Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : pub Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.7.1/language_concepts/02_control_flow.md deleted file mode 100644 index 691c514d9a..0000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/02_control_flow.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.7.1/language_concepts/03_ops.md deleted file mode 100644 index da02b12605..0000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.7.1/language_concepts/04_assert.md deleted file mode 100644 index a25a946123..0000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/04_assert.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. - -### Example - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -The above snippet compiles because `==` is a predicate operation. Conversely, the following will not -compile: - -```rust -// INCORRECT - -fn main(x : Field, y : Field) { - assert(x + y); -} -``` - -> The rationale behind this not compiling is due to ambiguity. It is not clear if the above should -> equate to `x + y == 0` or if it should check the truthiness of the result. diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.7.1/language_concepts/06_generics.md deleted file mode 100644 index 66f2e85e16..0000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/06_generics.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Generics -description: - Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -# Generics - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: comptime Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.7.1/language_concepts/07_mutability.md deleted file mode 100644 index 5631a32265..0000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/07_mutability.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in Noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a } -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -Comptime values are values that are known at compile-time. This is different to a witness -which changes per proof. If a comptime value that is being used in your program is changed, then your -circuit will also change. - -Comptime is slightly different from Rust's `const`. Namely, it is a bit more flexible in that normal functions can accept comptime parameters. For example, this is used to verify an array index is known at compile-time. Note that the "known at compile-time" here means "known after function inlining is performed while optimizing the program" and not "known during type-checking." - -Below we show how to declare a comptime value: - -```rust -fn main() { - let a: comptime Field = 5; - - // `comptime Field` can also be inferred: - let a = 5; -} -``` - -Note that variables declared as mutable may not be comptime: - -```rust -fn main() { - // error: Cannot mark a comptime type as mutable - let mut a: comptime Field = 5; - - // a inferred as a private Field here - let mut a = 5; -} -``` - -## Globals - -Noir also supports global variables. However, they must be compile-time variables. If `comptime` is -not explicitly written in the type annotation the compiler will implicitly specify the declaration -as compile-time. They can then be used like any other compile-time variable inside functions. The -global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: comptime Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * mysubmodule::N; - assert(res != res2); -} - -mod mysubmodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> comptime Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/08_comments.md b/docs/versioned_docs/version-v0.7.1/language_concepts/08_comments.md deleted file mode 100644 index 5b1d9fa38f..0000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/08_comments.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Comments -description: - Learn how to write comments in Noir programming language. A comment is a line of code that is - ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments - are supported in Noir. -keywords: [Noir programming language, comments, single-line comments, multi-line comments] ---- - -A comment is a line in your codebase which the compiler ignores, however it can be read by -programmers. - -Here is a single line comment: - -```rust -// This is a comment and is ignored -``` - -`//` is used to tell the compiler to ignore the rest of the line. - -Noir doesn't have multi-line comments, but you can emulate them via using `//` on each line - -```rust -// This is a multi line -// comment, that is ignored by -// the compiler -``` diff --git a/docs/versioned_docs/version-v0.7.1/language_concepts/09_distinct.md b/docs/versioned_docs/version-v0.7.1/language_concepts/09_distinct.md deleted file mode 100644 index 03759d4bb4..0000000000 --- a/docs/versioned_docs/version-v0.7.1/language_concepts/09_distinct.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Distinct Witnesses ---- - -The `distinct` keyword prevents repetitions of witness indices in the program's ABI. This ensures -that the witnesses being returned as public inputs are all unique. - -The `distinct` keyword is only used for return values on program entry points (usually the `main()` -function). - -When using `disctinct` and `pub` simultaneously, `distinct` comes first. See the example below. - -You can read more about the problem this solves -[here](https://github.com/noir-lang/noir/issues/1183). - -## Example - -Without the `distinct` keyword, the following program - -```rust -fn main(x : pub Field, y : pub Field) -> pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - "return_witnesses": [3, 2, 4, 4] - } -} -``` - -Whereas (with the `distinct` keyword) - -```rust -fn main(x : pub Field, y : pub Field) -> distinct pub [Field; 4] { - let a = 1; - let b = 1; - [x + 1, y, a, b] -} -``` - -compiles to - -```json -{ - //... - "abi": { - //... - "param_witnesses": { "x": [1], "y": [2] }, - //... - "return_witnesses": [3, 4, 5, 6] - } -} -``` diff --git a/docs/versioned_docs/version-v0.7.1/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.7.1/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 34f28a7114..0000000000 --- a/docs/versioned_docs/version-v0.7.1/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Crates and Packages -description: - Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in one of two forms: a binary crate or a library crate. - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/docs/versioned_docs/version-v0.7.1/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.7.1/modules_packages_crates/dependencies.md deleted file mode 100644 index 2807ad5204..0000000000 --- a/docs/versioned_docs/version-v0.7.1/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Managing Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -``` -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── liba - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -libA = { path = "../liba" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: - -```rust -use dep::ecrecover; -use dep::libA; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/docs/versioned_docs/version-v0.7.1/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.7.1/modules_packages_crates/modules.md deleted file mode 100644 index e429b33651..0000000000 --- a/docs/versioned_docs/version-v0.7.1/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Understanding Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -# Modules - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organise files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree -All modules are accessible from the ``crate::`` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` -In the above snippet, if ``bar`` would like to use functions in ``foo``, it can do so by ``use crate::foo::function_name``. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/docs/versioned_docs/version-v0.7.1/nargo/01_commands.md b/docs/versioned_docs/version-v0.7.1/nargo/01_commands.md deleted file mode 100644 index 8efa286b5f..0000000000 --- a/docs/versioned_docs/version-v0.7.1/nargo/01_commands.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -``` -Options: - -s, --show-ssa Emit debug information for the intermediate SSA IR - -d, --deny-warnings Quit execution when warnings are emitted - --show-output Display output of `println` statements during tests - -h, --help Print help -``` - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -- `` - The subcommand whose help message to display - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -## `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -## `nargo compile ` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -_Arguments_ - -- `` - The name of the circuit file - -_Options_ - -- `-c, --contracts` - Compile each contract function used within the program -- `--print-acir` - Displays the ACIR for the compiled circuit - -## `nargo new [path]` - -Creates a new Noir project. - -_Arguments_ - -- `` - Name of the package -- `[path]` - The path to save the new project - -## `nargo execute [witness_name]` - -Runs the Noir program and prints its return value. - -_Arguments_ - -- `[witness_name]` - The name of the witness - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `witness-name` argument. A -`.tr` file will then be saved in the `build` folder. - -> **Info:** The `.tr` file is the witness file. The witness file can be considered as program inputs -> parsed for your program's ACIR. -> -> This file can be passed along with circuit's ACIR into a TypeScript project for proving and -> verification. See the [TypeScript](../typescript#proving-and-verifying-externally-compiled-files) -> section to learn more. - -## `nargo prove ` - -Creates a proof for the program. - -_Arguments_ - -- `` - The name of the proof - -_Options_ - -- `-v, --verify` - Verify proof after proving - -## `nargo verify ` - -Given a proof and a program, verify whether the proof is valid. - -_Arguments_ - -- `` - The proof to verify - -## `nargo test ` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -See an example on the [testing page](./testing). - -_Arguments_ - -- `` - a pattern to indicate to only run tests with names containing the pattern - -## `nargo gates` - -Counts the occurrences of different gates in circuit - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). diff --git a/docs/versioned_docs/version-v0.7.1/nargo/02_testing.md b/docs/versioned_docs/version-v0.7.1/nargo/02_testing.md deleted file mode 100644 index ba0bebd658..0000000000 --- a/docs/versioned_docs/version-v0.7.1/nargo/02_testing.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -This is much faster compared to testing in Typescript but the only downside is that you can't -explicitly test that a certain set of inputs are invalid. i.e. you can't say that you want -add(2^64-1, 2^64-1) to fail. diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/array_methods.md b/docs/versioned_docs/version-v0.7.1/standard_library/array_methods.md deleted file mode 100644 index 8d8a953124..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/array_methods.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -title: Array Methods -description: - Learn about the commonly used methods available for arrays in Noir, including len, sort, fold, - reduce, all, and any. -keywords: [rust, array, methods, len, sort, fold, reduce, all, any] ---- - -# Array - -For convenience, the STD provides some ready-to-use, common methods for arrays[^migrationnote]: - -## len - -Returns the length of an array - -```rust -fn len(_array: [T; N]) -> comptime Field -``` - -example - -```rust -fn main() { - let array = [42, 42]; - assert(array.len() == 2); -} -``` - -## sort - -Returns a new sorted array. The original array remains untouched. Notice that this function will -only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting -logic it uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_array: [T; N]) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32]; - let sorted = arr.sort(); - assert(sorted == [32, 42]); -} -``` - -## sort_via - -Sorts the array with a custom comparison function - -```rust -fn sort_via(mut a: [T; N], ordering: fn(T, T) -> bool) -> [T; N] -``` - -example - -```rust -fn main() { - let arr = [42, 32] - let sorted_ascending = arr.sort_via(|a, b| a < b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = arr.sort_via(|a, b| a > b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -## map - -Applies a function to each element of the array, returning a new array containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U; N] -``` - -example - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2); // b is now [2, 4, 6] -``` - -## fold - -Applies a function to each element of the array, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the array, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -example: - -```rust - -fn main() { - let arr = [2, 2, 2, 2, 2]; - let folded = arr.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -## reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let reduced = arr.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -## all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 2]; - let all = arr.all(|a| a == 2); - assert(all); -} -``` - -## any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -example: - -```rust -fn main() { - let arr = [2, 2, 2, 2, 5]; - let any = arr.any(|a| a == 5); - assert(any); -} - -``` - -[^migrationnote]: - Migration Note: These methods were previously free functions, called via `std::array::len()`. - For the sake of ease of use and readability, these functions are now methods and the old syntax - for them is now deprecated. diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.7.1/standard_library/black_box_fns.md deleted file mode 100644 index 3063e71c14..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/black_box_fns.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen](./cryptographic_primitives/hashes#pedersen) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_secp256k1) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives.md deleted file mode 100644 index 2df4f92947..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic primitives in Noir -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index 31a84cdb75..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::pedersen(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index 62265cddb1..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: - See how you can perform scalar multiplications over a fixed base in Noir -keywords: - [ - cryptographic primitives, - Noir project, - scalar multiplication, - ] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## scalar_mul::fixed_base - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base(x); - std::println(scal); -} -``` - - diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index 0e219c0e5f..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx deleted file mode 100644 index 0b800fdbc5..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: ECDSA Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 curve -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - - diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/04_ec_primitives.md deleted file mode 100644 index 26fb4c09e8..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/04_ec_primitives.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Elliptic Curve Primitives -keywords: [cryptographic primitives, Noir project] ---- - -Data structures and methods on them that allow you to carry out computations involving elliptic -curves over the (mathematical) field corresponding to `Field`. For the field currently at our -disposal, applications would involve a curve embedded in BN254, e.g. the -[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). - -## Data structures - -### Elliptic curve configurations - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic -curve you want to use, which would be specified using any one of the methods -`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the -defining equation together with a generator point as parameters. You can find more detail in the -comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but -the gist of it is that the elliptic curves of interest are usually expressed in one of the standard -forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, -you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly -together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates -requiring more coordinates but allowing for more efficient implementations of elliptic curve -operations). Conversions between all of these forms are provided, and under the hood these -conversions are done whenever an operation is more efficient in a different representation (or a -mixed coordinate representation is employed). - -### Points - -(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the -elliptic curve. For a curve configuration `c` and a point `p`, it may be checked checked that `p` -does indeed lie on `c` by calling `c.contains(p1)`. - -## Methods - -(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use -`std::ec::tecurve::affine::Point`) - -- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is - zero by calling `p.is_zero()`. -- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling - `p1.eq(p2)`. -- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two - points is accomplished by calling `c.add(p1,p2)`. -- **Negation**: For a point `p: Point`, `p.negate()` is its negation. -- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by - calling `c.subtract(p1,p2)`. -- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, - scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit - array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` -- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, - multi-scalar multiplication is given by `c.msm(n,p)`. -- **Coordinate representation conversions**: The `into_group` method converts a point or curve - configuration in the affine representation to one in the CurveGroup representation, and - `into_affine` goes in the other direction. -- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent - and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their - configurations or points. `swcurve` is more general and a curve c of one of the other two types - may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying - on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling - `c.map_into_swcurve(p)`. -- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a - `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of - the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where - `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to - satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). - -## Examples - -The -[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/crates/nargo_cli/tests/test_data/ec_baby_jubjub/src/main.nr) -illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more -interesting examples in Noir would be: - -Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key -from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, -for example, this code would do: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; - -fn bjj_pub_key(priv_key: Field) -> Point -{ - - let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - - let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); - - bjj.mul(priv_key,base_pt) -} -``` - -This would come in handy in a Merkle proof. - -- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash - function. See - [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for - the case of Baby Jubjub and the Poseidon hash function. diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/05_eddsa.mdx deleted file mode 100644 index 8f060ed331..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/05_eddsa.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/common/_blackbox.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/common/_blackbox.mdx deleted file mode 100644 index 9fe9b48fbf..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/common/_blackbox.mdx +++ /dev/null @@ -1,5 +0,0 @@ -:::info - -This is a black box function. Read [this section](../black_box_fns) to learn more about black box functions in Noir. - -::: \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md b/docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md deleted file mode 100644 index 4d1cdc953e..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Field Methods -description: - Learn about common methods on Noir Field, including to_le_bits, to_le_bytes, to_le_radix, - to_be_radix, pow_32, etc, and see code examples. -keywords: - [ - Noir Field, - to_le_bits, - to_le_bytes, - to_le_radix, - to_be_radix, - pow_32, - Little Endian, - Big Endian, - Vector, - Exponent, - ] ---- - -After declaring a Field, you can use these common methods on it: - -## to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2 - let bits = field.to_le_bits(32); -} -``` - -## to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2 - let bits = field.to_be_bits(32); -} -``` - -## to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let bytes = field.to_le_bytes(4); -} -``` - -## to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let bytes = field.to_be_bytes(4); -} -``` - -## to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let radix = field.to_le_radix(256, 4); -} -``` - -## to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let radix = field.to_be_radix(256, 4); -} -``` - -## pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -## sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/logging.md b/docs/versioned_docs/version-v0.7.1/standard_library/logging.md deleted file mode 100644 index 649d35a3f0..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/logging.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -# Logging - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -The `println` statement only works for fields, integers and arrays (including strings). - -```rust -use dep::std; - -fn main(string: pub str<5>) { - let x = 5; - std::println(x) -} - -``` - -To view the output of the `println` statement you need to set the `--show-output` flag. - -``` -$ nargo prove --help -Create proof for this program. The proof is returned as a hex encoded string - -Usage: nargo prove [OPTIONS] [PROOF_NAME] [CIRCUIT_NAME] - -Arguments: - [PROOF_NAME] The name of the proof - [CIRCUIT_NAME] The name of the circuit build files (ACIR, proving and verification keys) - -Options: - -v, --verify Verify proof after proving - -s, --show-ssa Emit debug information for the intermediate SSA IR - -d, --deny-warnings Quit execution when warnings are emitted - --show-output Display output of `println` statements during tests - -h, --help Print help -``` diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.7.1/standard_library/merkle_trees.md deleted file mode 100644 index fc8909a479..0000000000 --- a/docs/versioned_docs/version-v0.7.1/standard_library/merkle_trees.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Merkle Trees -description: - Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.7.1/typescript.md b/docs/versioned_docs/version-v0.7.1/typescript.md deleted file mode 100644 index fae002dfd2..0000000000 --- a/docs/versioned_docs/version-v0.7.1/typescript.md +++ /dev/null @@ -1,262 +0,0 @@ ---- -title: Working with TypeScript -description: - Learn how to interact with Noir programs using TypeScript. Follow this tutorial to compile your - program, specify inputs, initialize a prover & verifier, and prove and verify your program. -keywords: [TypeScript, Noir, tutorial, compile, inputs, prover, verifier, proof] ---- - -Interactions with Noir programs can also be performed in TypeScript, which can come in handy when -writing tests or when working in TypeScript-based projects like [Hardhat](https://hardhat.org/). - -This guide is based on the [noir-starter](https://github.com/signorecello/noir-starter) example. -Please refer to it for an example implementation. - -:::note - -You may find unexpected errors working with some frameworks such as `vite`. This is due to the -nature of `wasm` files and the way Noir uses web workers. As we figure it out, we suggest using -[Create React App](https://create-react-app.dev/), or [Next.js](https://nextjs.org/) for a quick -start. - -::: - -## Setup - -We're assuming you're using ES6 for both browser (for example with React), or nodejs. - -Install [Yarn](https://yarnpkg.com/) or [Node.js](https://nodejs.org/en). Init a new project with -`npm init`. Install Noir dependencies in your project by running: - -```bash -npm i @noir-lang/noir_wasm@0.3.2-fa0e9cff github:noir-lang/barretenberg#39a1547875f941ef6640217a42d8f34972425c97 @noir-lang/aztec_backend@0.1.0-0c3b2f2 -``` - -:::note - -While Noir is in rapid development, some packages could interfere with others. For that reason, you -should use these specified versions. Let us know if for some reason you need to use other ones. - -::: - -As for the circuit, we will use the _Standard Noir Example_ and place it in the `src` folder. Feel -free to use any other, as long as you refactor the below examples accordingly. - -This standard example is a program that multiplies input `x` with input `y` and returns the result: - -```rust -// src/main.nr -fn main(x: u32, y: pub u32) -> pub u32 { - let z = x * y; - z -} -``` - -One valid scenario for proving could be `x = 3`, `y = 4` and `return = 12` - -## Imports - -We need some imports, for both the `noir_wasm` library (which will compile the circuit into `wasm` -executables) and `aztec_backend` which is the actual proving backend we will be using. - -We also need to tell the compiler where to find the `.nr` files, so we need to import -`initialiseResolver`. - -```ts -import initNoirWasm, { acir_read_bytes, compile } from '@noir-lang/noir_wasm'; -import initialiseAztecBackend from '@noir-lang/aztec_backend'; -import { initialiseResolver } from '@noir-lang/noir-source-resolver'; -``` - -## Compiling - -We'll go over the code line-by-line later: - -```ts -export const compileCircuit = async () => { - await initNoirWasm(); - - return await fetch(new URL('../src/main.nr', import.meta.url)) - .then(r => r.text()) - .then(code => { - initialiseResolver((id: any) => { - return code; - }); - }) - .then(() => { - try { - const compiled_noir = compile({}); - return compiled_noir; - } catch (e) { - console.log('Error while compiling:', e); - } - }); -}; -``` - -1. First we're calling `initNoirWasm`. This is required on the browser only. -2. We then pass an URL that points to our `main.nr` file, and call `.then` on it so we can get the - actual text of the source code -3. We call `initialiseResolver` returning the source code -4. Finally, we can call the `compile` function - -This function should return us the compiled circuit. - -:::note - -You can use as many files as you need, -[importing them as you would do with Nargo](./modules_packages_crates/dependencies), and you don't -need to set them up in the `src` folder. Just mind the following particularities about -`initialiseResolver`: - -1. The `compile` function expects a `main.nr` file as an entry point. If you need another one, just - pass it as a `entry_point` parameter to `compile`. Check the - [noir starter](https://github.com/signorecello/noir-starter) for an example on multiple files and - a non-default entry point. -2. `initialiseResolver` needs to be synchronous -3. Different frameworks use different ways of fetching files. It's beyond the scope of this guide to - explain why and how, but for reference, - [noir starter](https://github.com/signorecello/noir-starter) uses both Next.js and node.js for - testing. - -Quick tip: an easy way to deal with `initialiseResolver` is just to prepare a -`{fileName: "literally_the_code"}` object beforehand - -::: - -## ACIR - -Noir compiles to two properties: - -1. The ACIR, which is the intermediate language used by backends such as Barretenberg -2. The ABI, which tells you which inputs are to be read - -Let's write a little function that gets us both, initializes the backend, and returns the ACIR as -bytes: - -```ts -export const getAcir = async () => { - const { circuit, abi } = await compileCircuit(); - await initialiseAztecBackend(); - - let acir_bytes = new Uint8Array(Buffer.from(circuit, 'hex')); - return acir_read_bytes(acir_bytes); -}; -``` - -Calling `getAcir()` now should return us the ACIR of the circuit, ready to be used in proofs. - -## Initializing Prover & Verifier - -Prior to proving and verifying, the prover and verifier have to first be initialized by calling -`barretenberg`'s `setup_generic_prover_and_verifier` with your Noir program's ACIR: - -```ts -let [prover, verifier] = await setup_generic_prover_and_verifier(acir); -``` - -This is probably a good time to store this prover and verifier into your state like React Context, -Redux, or others. - -## Proving - -The Noir program can then be executed and proved by calling `barretenberg`'s `create_proof` -function: - -```ts -const proof = await create_proof(prover, acir, abi); -``` - -On the browser, this proof can fail as it requires heavy loads to be run on worker threads. Here's a -quick example of a worker: - -```ts -// worker.ts -onmessage = async event => { - try { - await initializeAztecBackend(); - const { acir, input } = event.data; - const [prover, verifier] = await setup_generic_prover_and_verifier(acir); - const proof = await create_proof(prover, acir, input); - postMessage(proof); - } catch (er) { - postMessage(er); - } finally { - close(); - } -}; -``` - -Which would be called like this, for example: - -```ts -// index.ts -const worker = new Worker(new URL('./worker.ts', import.meta.url)); -worker.onmessage = e => { - if (e.data instanceof Error) { - // oh no! - } else { - // yey! - } -}; -worker.postMessage({ acir, input: { x: 3, y: 4 } }); -``` - -## Verifying - -The `proof` obtained can be verified by calling `barretenberg`'s `verify_proof` function: - -```ts -// 1_mul.ts -const verified = await verify_proof(verifier, proof); -``` - -The function should return `true` if the entire process is working as intended, which can be -asserted if you are writing a test script: - -```ts -expect(verified).eq(true); -``` - -## Verifying with Smart Contract - -Alternatively, a verifier smart contract can be generated and used for verifying Noir proofs in -TypeScript as well. - -This could be useful if the Noir program is designed to be decentrally verified and/or make use of -decentralized states and logics that is handled at the smart contract level. - -To generate the verifier smart contract using typescript: - -```ts -// generator.ts -import { writeFileSync } from 'fs'; - -const sc = verifier.SmartContract(); -syncWriteFile('../contracts/plonk_vk.sol', sc); - -function syncWriteFile(filename: string, data: any) { - writeFileSync(join(__dirname, filename), data, { - flag: 'w', - }); -} -``` - -You can then verify a Noir proof using the verifier contract, for example using Hardhat: - -```ts -// verifier.ts -import { ethers } from 'hardhat'; -import { Contract, ContractFactory, utils } from 'ethers'; - -let Verifier: ContractFactory; -let verifierContract: Contract; - -before(async () => { - Verifier = await ethers.getContractFactory('TurboVerifier'); - verifierContract = await Verifier.deploy(); -}); - -// Verify proof -const sc_verified = await verifierContract.verify(proof); -``` diff --git a/docs/versioned_docs/version-v0.9.0/examples/merkle-proof.mdx b/docs/versioned_docs/version-v0.9.0/examples/merkle-proof.mdx deleted file mode 100644 index 6430780817..0000000000 --- a/docs/versioned_docs/version-v0.9.0/examples/merkle-proof.mdx +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Merkle Proof Membership -description: - Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a - merkle tree with a specified root, at a given index. -keywords: - [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] ---- - -Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is -in a merkle tree. - -```rust -use dep::std; - -fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { - let leaf = std::hash::hash_to_field(message); - let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); - assert(merkle_root == root); -} - -``` - -The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen -by the backend. The only requirement is that this hash function can heuristically be used as a -random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen` -instead. - -```rust -let leaf = std::hash::hash_to_field(message); -``` - -The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. - -```rust -let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); -assert (merkle_root == root); -``` - -> **Note:** It is possible to re-implement the merkle tree implementation without standard library. -> However, for most usecases, it is enough. In general, the standard library will always opt to be -> as conservative as possible, while striking a balance with efficiency. - -An example, the merkle membership proof, only requires a hash function that has collision -resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient -than the even more conservative sha256. - -[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md deleted file mode 100644 index de30869732..0000000000 --- a/docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md +++ /dev/null @@ -1,285 +0,0 @@ ---- -title: Nargo Installation -description: - nargo is a command line tool for interacting with Noir programs (e.g. compiling, proving, - verifying and more). Learn how to install and use Nargo for your projects with this comprehensive - guide. -keywords: [Nargo, command line tool, Noir programs, installation guide, how to use Nargo] ---- - -`nargo` is a command line tool for interacting with Noir programs (e.g. compiling, proving, -verifying and more). - -Alternatively, the interactions can also be performed in [TypeScript](../typescript). - -### UltraPlonk - -Nargo versions <0.5.0 of `aztec_backend` and `aztec_wasm_backend` are based on the TurboPlonk -version of Aztec Backend, which lacks efficient implementations of useful primitives (e.g. Keccak256 in 18k constraints, ECDSA verification in 36k constraints) that the UltraPlonk version offers. - -## Installation - -There are four approaches for installing Nargo: - -- [Option 1: Noirup](#option-1-noirup) -- [Option 2: Binaries](#option-2-binaries) -- [Option 3: Install via Nix](#option-3-install-via-nix) -- [Option 4: Compile from Source](#option-4-compile-from-source) - -Optionally you can also install [Noir VS Code extension] for syntax highlighting. - -### Option 1: Noirup - -If you're on OSX or Linux, the easiest way to start using Noir and Nargo is via noirup. Just open a -terminal and run: - -```bash -curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash -``` - -Close the terminal, open another one, and run - -```bash -noirup -``` - -Done, you should have the latest version working. You can check with `nargo --version`. - -You can also install nightlies, specific versions -or branches, check out the [noirup repository](https://github.com/noir-lang/noirup) for more -information. - -#### GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) in -this repo containing hash functions in Noir for an example. - -#### Nightly versions - -To install the nightly version of Noir (updated daily) run: - -```bash -noirup -n -``` - -### Option 2: Binaries - -See [GitHub Releases](https://github.com/noir-lang/noir/releases) for the latest and previous -platform specific binaries. - -#### Step 1 - -Paste and run the following in the terminal to extract and install the binary: - -> **macOS / Linux:** If you are prompted with `Permission denied` when running commands, prepend -> `sudo` and re-run it. - -##### macOS (Apple Silicon) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-aarch64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### macOS (Intel) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-apple-darwin.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \ -echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \ -source ~/.zshrc -``` - -##### Windows (PowerShell) - -Open PowerShell as Administrator and run: - -```powershell -mkdir -f -p "$env:USERPROFILE\.nargo\bin\"; ` -Invoke-RestMethod -Method Get -Uri https://github.com/noir-lang/noir/releases/download/v0.4.1/nargo-x86_64-pc-windows-msvc.zip -Outfile "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip"; ` -Expand-Archive -Path "$env:USERPROFILE\.nargo\bin\nargo-x86_64-pc-windows-msvc.zip" -DestinationPath "$env:USERPROFILE\.nargo\bin\"; ` -$Reg = "Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment"; ` -$OldPath = (Get-ItemProperty -Path "$Reg" -Name PATH).Path; ` -$NewPath = $OldPath + ’;’ + "$env:USERPROFILE\.nargo\bin\"; ` -Set-ItemProperty -Path "$Reg" -Name PATH –Value "$NewPath"; ` -$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") -``` - -##### Linux (Bash) - -```bash -mkdir -p $HOME/.nargo/bin && \ -curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.6.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \ -tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \ -echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \ -source ~/.bashrc -``` - -#### Step 2 - -Check if the installation was successful by running `nargo --help`. - -> **macOS:** If you are prompted with an OS alert, right-click and open the _nargo_ executable from -> Finder. Close the new terminal popped up and `nargo` should now be accessible. - -For a successful installation, you should see something similar to the following after running the -command: - -```sh -$ nargo --help - -Noir's package manager - -Usage: nargo - -Commands: - check Checks the constraint system for errors - codegen-verifier Generates a Solidity verifier smart contract for the program - compile Compile the program and its secret execution trace into ACIR format - new Create a new binary project - execute Executes a circuit to calculate its return value - prove Create proof for this program. The proof is returned as a hex encoded string - verify Given a proof and a program, verify whether the proof is valid - test Run the tests for this program - gates Counts the occurrences of different gates in circuit - help Print this message or the help of the given subcommand(s) -``` - -### Option 3: Install via Nix - -Due to the large number of native dependencies, Noir projects can be installed via [Nix](https://nixos.org/). - -#### Installing Nix - -For the best experience, please follow these instructions to setup Nix: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -#### Install Nargo into your Nix profile - -1. Use `nix profile` to install Nargo - -```sh -nix profile install github:noir-lang/noir -``` - -### Option 4: Compile from Source - -Due to the large number of native dependencies, Noir projects uses [Nix](https://nixos.org/) and [direnv](https://direnv.net/) to streamline the development experience. - -#### Setting up your environment - -For the best experience, please follow these instructions to setup your environment: - -1. Install Nix following [their guide](https://nixos.org/download.html) for your operating system. -2. Create the file `~/.config/nix/nix.conf` with the contents: - -```ini -experimental-features = nix-command -extra-experimental-features = flakes -``` - -3. Install direnv into your Nix profile by running: - -```sh -nix profile install nixpkgs#direnv -``` - -4. Add direnv to your shell following [their guide](https://direnv.net/docs/hook.html). - 1. For bash or zshell, add `eval "$(direnv hook bash)"` or `eval "$(direnv hook zsh)"` to your ~/.bashrc or ~/.zshrc file, respectively. -5. Restart your shell. - -#### Shell & editor experience - -Now that your environment is set up, you can get to work on the project. - -1. Clone the repository, such as: - -```sh -git clone git@github.com:noir-lang/noir -``` - -> Replacing `noir` with whichever repository you want to work on. - -2. Navigate to the directory: - -```sh -cd noir -``` - -> Replacing `noir` with whichever repository you cloned. - -3. You should see a **direnv error** because projects aren't allowed by default. Make sure you've reviewed and trust our `.envrc` file, then you need to run: - -```sh -direnv allow -``` - -4. Now, wait awhile for all the native dependencies to be built. This will take some time and direnv will warn you that it is taking a long time, but we just need to let it run. - -5. Once you are presented with your prompt again, you can start your editor within the project directory (we recommend [VSCode](https://code.visualstudio.com/)): - -```sh -code . -``` - -6. (Recommended) When launching VSCode for the first time, you should be prompted to install our recommended plugins. We highly recommend installing these for the best development experience. - -#### Building and testing - -Assuming you are using `direnv` to populate your environment, building and testing the project can be done -with the typical `cargo build`, `cargo test`, and `cargo clippy` commands. You'll notice that the `cargo` version matches the version we specify in `flake.nix`, which is 1.66.0 at the time of this writing. - -If you want to build the entire project in an isolated sandbox, you can use Nix commands: - -1. `nix build .` (or `nix build . -L` for verbose output) to build the project in a Nix sandbox. -2. `nix flake check` (or `nix flake check -L` for verbose output) to run clippy and tests in a Nix sandbox. - -#### Without `direnv` - -If you have hesitations with using direnv, you can launch a subshell with `nix develop` and then launch your editor from within the subshell. However, if VSCode was already launched in the project directory, the environment won't be updated. - -Advanced: If you aren't using direnv nor launching your editor within the subshell, you can try to install Barretenberg and other global dependencies the package needs. This is an advanced workflow and likely won't receive support! - -## Uninstalling Nargo - -### Noirup - -If you installed Noir with `noirup`, you can uninstall Noir by removing the files in `~/.nargo`, `~/nargo` and `~/noir_cache`. - -```bash -rm -r ~/.nargo -rm -r ~/nargo -rm -r ~/noir_cache -``` - -### Nix - -If you installed Noir with Nix or from source, you can remove the binary located at `~/.nix-profile/bin/nargo`. - -```bash -rm ~/.nix-profile/bin/nargo -``` - -[git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git -[rust]: https://www.rust-lang.org/tools/install -[noir vs code extension]: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir -[homebrew]: https://brew.sh/ -[cmake]: https://cmake.org/install/ -[llvm]: https://llvm.org/docs/GettingStarted.html -[openmp]: https://openmp.llvm.org/ -[barretenberg]: https://github.com/AztecProtocol/barretenberg diff --git a/docs/versioned_docs/version-v0.9.0/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.9.0/getting_started/01_hello_world.md deleted file mode 100644 index 0f21ad4556..0000000000 --- a/docs/versioned_docs/version-v0.9.0/getting_started/01_hello_world.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Create A Project -description: - Learn how to create and verify your first Noir program using Nargo, a programming language for - zero-knowledge proofs. -keywords: - [ - Nargo, - Noir, - zero-knowledge proofs, - programming language, - create Noir program, - verify Noir program, - step-by-step guide, - ] ---- - -Now that we have installed Nargo, it is time to make our first hello world program! - -## Create a Project Directory - -Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home -directory to house our Noir programs. - -For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by -running: - -```sh -mkdir ~/projects -cd ~/projects -``` - -For Windows CMD, run: - -```sh -> mkdir "%USERPROFILE%\projects" -> cd /d "%USERPROFILE%\projects" -``` - -## Create Our First Nargo Project - -Now that we are in the projects directory, create a new Nargo project by running: - -```sh -nargo new hello_world -``` - -> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for -> demonstration. -> -> In production, the common practice is to name the project folder as `circuits` for better -> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, -> `test`). - -A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and -_Nargo.toml_ that contains the source code and environmental options of your Noir program -respectively. - -### Intro to Noir Syntax - -Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: - -```rust -fn main(x : Field, y : pub Field) { - assert(x != y); -} -``` - -The first line of the program specifies the program's inputs: - -```rust -x : Field, y : pub Field -``` - -Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the -keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. - -The next line of the program specifies its body: - -```rust -assert(x != y); -``` - -The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. - -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. - -## Build In/Output Files - -Change directory into _hello_world_ and build in/output files for your Noir program by running: - -```sh -cd hello_world -nargo check -``` - -Two additional files would be generated in your project directory: - -_Prover.toml_ houses input values, and _Verifier.toml_ houses public values. - -## Prove Our Noir Program - -Now that the project is set up, we can create a proof of correct execution on our Noir program. - -Fill in input values for execution in the _Prover.toml_ file. For example: - -```toml -x = "1" -y = "2" -``` - -Prove the valid execution of your Noir program with your preferred proof name, for example `p`: - -```sh -nargo prove p -``` - -A new folder _proofs_ would then be generated in your project directory, containing the proof file -`p.proof`. - -The _Verifier.toml_ file would also be updated with the public values computed from program -execution (in this case the value of `y`): - -```toml -y = "0x0000000000000000000000000000000000000000000000000000000000000002" -``` - -> **Note:** Values in _Verifier.toml_ are computed as 32-byte hex values. - -## Verify Our Noir Program - -Once a proof is generated, we can verify correct execution of our Noir program by verifying the -proof file. - -Verify your proof of name `p` by running: - -```sh -nargo verify p -``` - -The verification will complete in silence if it is successful. If it fails, it will log the -corresponding error instead. - -Congratulations, you have now created and verified a proof for your very first Noir program! - -In the [next section](breakdown), we will go into more detail on each step performed. diff --git a/docs/versioned_docs/version-v0.9.0/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.9.0/getting_started/02_breakdown.md deleted file mode 100644 index 7c320cef9c..0000000000 --- a/docs/versioned_docs/version-v0.9.0/getting_started/02_breakdown.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -title: Project Breakdown -description: - Learn about the anatomy of a Nargo project, including the purpose of the Prover and Verifier TOML - files, and how to prove and verify your program. -keywords: - [Nargo, Nargo project, Prover.toml, Verifier.toml, proof verification, private asset transfer] ---- - -This section breaks down our hello world program in section _1.2_. We elaborate on the project -structure and what the `prove` and `verify` commands did in the previous section. - -## Anatomy of a Nargo Project - -Upon creating a new project with `nargo new` and building the in/output files with `nargo check` -commands, you would get a minimal Nargo project of the following structure: - - - src - - Prover.toml - - Verifier.toml - - Nargo.toml - -The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ -file will be generated within it. - -_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. - -_Verifier.toml_ contains public in/output values computed when executing the Noir program. - -_Nargo.toml_ contains the environmental options of your project. - -_proofs_ and _contract_ directories will not be immediately visible until you create a proof or -verifier contract respectively. - -### main.nr - -The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. - -In our sample program, _main.nr_ looks like this: - -```rust -fn main(x : Field, y : Field) { - assert(x != y); -} -``` - -The parameters `x` and `y` can be seen as the API for the program and must be supplied by the -prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when -verifying the proof. - -The prover supplies the values for `x` and `y` in the _Prover.toml_ file. - -As for the program body, `assert` ensures the satisfaction of the condition (e.g. `x != y`) is -constrained by the proof of the execution of said program (i.e. if the condition was not met, the -verifier would reject the proof as an invalid proof). - -### Prover.toml - -The _Prover.toml_ file is a file which the prover uses to supply his witness values(both private and -public). - -In our hello world program the _Prover.toml_ file looks like this: - -```toml -x = "1" -y = "2" -``` - -When the command `nargo prove my_proof` is executed, two processes happen: - -1. Noir creates a proof that `x` which holds the value of `1` and `y` which holds the value of `2` - is not equal. This not equal constraint is due to the line `assert(x != y)`. - -2. Noir creates and stores the proof of this statement in the _proofs_ directory and names the proof - file _my_proof_. Opening this file will display the proof in hex format. - -#### Arrays of Structs - -The following code shows how to pass an array of structs to a Noir program to generate a proof. - -```rust -// main.nr -struct Foo { - bar: Field, - baz: Field, -} - -fn main(foos: [Foo; 3]) -> pub Field { - foos[2].bar + foos[2].baz -} -``` - -Prover.toml: - -```toml -[[foos]] # foos[0] -bar = 0 -baz = 0 - -[[foos]] # foos[1] -bar = 0 -baz = 0 - -[[foos]] # foos[2] -bar = 1 -baz = 2 -``` - -#### Custom toml files - -You can specify a `toml` file with a different name to use for proving by using the `--prover-name` or `-p` flags. - -This command looks for proof inputs in the default **Prover.toml** and generates proof `p`: - -```bash -nargo prove p -``` - -This command looks for proof inputs in the custom **OtherProver.toml** and generates proof `pp`: - -```bash -nargo prove -p OtherProver pp -``` - -## Verifying a Proof - -When the command `nargo verify my_proof` is executed, two processes happen: - -1. Noir checks in the _proofs_ directory for a file called _my_proof_ - -2. If that file is found, the proof's validity is checked - -> **Note:** The validity of the proof is linked to the current Noir program; if the program is -> changed and the verifier verifies the proof, it will fail because the proof is not valid for the -> _modified_ Noir program. - -In production, the prover and the verifier are usually two separate entities. A prover would -retrieve the necessary inputs, execute the Noir program, generate a proof and pass it to the -verifier. The verifier would then retrieve the public inputs from usually external sources and -verifies the validity of the proof against it. - -Take a private asset transfer as an example: - -A user on browser as the prover would retrieve private inputs (e.g. the user's private key) and -public inputs (e.g. the user's encrypted balance on-chain), compute the transfer, generate a proof -and submit it to the verifier smart contract. - -The verifier contract would then draw the user's encrypted balance directly from the blockchain and -verify the proof submitted against it. If the verification passes, additional functions in the -verifier contract could trigger (e.g. approve the asset transfer). - -Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. - -In the [next section](language_server), we will explain how to utilize the Noir Language Server. diff --git a/docs/versioned_docs/version-v0.9.0/getting_started/03_language_server.md b/docs/versioned_docs/version-v0.9.0/getting_started/03_language_server.md deleted file mode 100644 index e6f5dfc2fa..0000000000 --- a/docs/versioned_docs/version-v0.9.0/getting_started/03_language_server.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Language Server -description: - Learn about the Noir Language Server, how to install the components, and configuration that may be required. -keywords: - [Nargo, Language Server, LSP, VSCode, Visual Studio Code] ---- - -This section helps you install and configure the Noir Language Server. - -The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. - -## Language Server - -The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. -As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! - -If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. - -## Language Client - -The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. - -Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -### Configuration - -* __Noir: Enable LSP__ - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. -* __Noir: Nargo Flags__ - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. -* __Noir: Nargo Path__ - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. -* __Noir > Trace: Server__ - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/docs/versioned_docs/version-v0.9.0/index.md b/docs/versioned_docs/version-v0.9.0/index.md deleted file mode 100644 index e56b24bccd..0000000000 --- a/docs/versioned_docs/version-v0.9.0/index.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: Introducing Noir -description: - Learn about the public alpha release of Noir, a domain specific language heavily influenced by - Rust that compiles to an intermediate language which can be compiled to an arithmetic circuit or a - rank-1 constraint system. -keywords: - [ - Noir, - Domain Specific Language, - Rust, - Intermediate Language, - Arithmetic Circuit, - Rank-1 Constraint System, - Ethereum Developers, - Protocol Developers, - Blockchain Developers, - Proving System, - Smart Contract Language, - ] -slug: / ---- - -This version of the book is being released with the public alpha. There will be a lot of features -that are missing in this version, however the syntax and the feel of the language will mostly be -completed. - -## What is Noir? - -Noir is a Domain Specific Language for SNARK proving systems. It has been designed to use any ACIR compatible proving system. - -It's design choices are influenced heavily by Rust and focuses on a simple, familiar syntax. - -## Who is Noir for? - -Noir can be used for a variety of purposes. - -### Solidity Developers - -Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularised in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create -a verifier contract. - -### Protocol Developers - -As a protocol developer, you may not want to use the Aztec backend due to it not being a fit for -your stack, or maybe you simply want to use a different proving system. Since Noir does not compile -to a specific proof system, it is possible for protocol developers to replace the PLONK-based -proving system with a different proving system altogether. - -### Blockchain developers - -As a blockchain developer, you will be constrained by parameters set by your blockchain (for example, the -proving system and smart contract language has been pre-defined). In order for you to use Noir in -your blockchain, a proving system backend and a smart contract interface -must be implemented for it. - -## What's new about Noir? - -Noir is simple and flexible in its design, as it does not compile immediately to a fixed -NP-complete language. Instead, Noir compiles to an intermediate language (ACIR), which itself can be compiled -to an arithmetic circuit (if choosing to target Aztec's barretenberg backend) or a rank-1 constraint system (if choosing to target an R1CS backend like Arkwork's Marlin backend, or others). - -This in itself brings up a few challenges within the design process, but allows one to decouple the programming language completely from the backend. This is similar in theory to LLVM. - -## Current Features - -Compiler: - -- Module System -- For expressions -- Arrays -- Bit Operations -- Binary operations (<, <=, >, >=, +, -, \*, /, %) [See documentation for an extensive list] -- Unsigned integers -- If statements -- Structures and Tuples -- Generics - -ACIR Supported OPCODES: - -- Sha256 -- Blake2s -- Schnorr signature verification -- MerkleMembership -- Pedersen -- HashToField - -## Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers - -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/00_data_types.md b/docs/versioned_docs/version-v0.9.0/language_concepts/00_data_types.md deleted file mode 100644 index abbadca86b..0000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/00_data_types.md +++ /dev/null @@ -1,405 +0,0 @@ ---- -title: Data Types -description: - Get a clear understanding of the two categories of Noir data types - primitive types and compound - types. Learn about their characteristics, differences, and how to use them in your Noir - programming. -keywords: - [ - noir, - data types, - primitive types, - compound types, - private types, - public types, - field type, - integer types, - boolean type, - array type, - tuple type, - struct type, - ] ---- - -Every value in Noir has a type, which determines which operations are valid for it. - -All values in Noir are fundamentally composed of `Field` elements. For a more approachable -developing experience, abstractions are added on top to introduce different data types in Noir. - -Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound -types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or -public. - -## Private & Public Types - -A **private value** is known only to the Prover, while a **public value** is known by both the -Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All -primitive types (including individual fields of compound types) in Noir are private by default, and -can be marked public when certain values are intended to be revealed to the Verifier. - -> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once -> the proofs are verified on-chain the values can be considered known to everyone that has access to -> that blockchain. - -Public data types are treated no differently to private types apart from the fact that their values -will be revealed in proofs generated. Simply changing the value of a public type will not change the -circuit (where the same goes for changing values of private types as well). - -_Private values_ are also referred to as _witnesses_ sometimes. - -> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different -> meaning than when applied to a function (e.g. `pub fn foo() {}`). -> -> The former is a visibility modifier for the Prover to interpret if a value should be made known to -> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a -> function should be made accessible to external Noir programs like in other languages. - -### pub Modifier - -All data types in Noir are private by default. Types are explicitly declared as public using the -`pub` modifier: - -```rust -fn main(x : Field, y : pub Field) -> pub Field { - x + y -} -``` - -In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note -that visibility is handled **per variable**, so it is perfectly valid to have one input that is -private and another that is public. - -> **Note:** Public types can only be declared through parameters on `main`. - -## Primitive Types - -A primitive type represents a single value. They can be private or public. - -### Fields - -The field type corresponds to the native field type of the proving backend. - -The size of a Noir field depends on the elliptic curve's finite field for the proving backend -adopted. For example, a field would be a 254-bit integer when paired with the default backend that -spans the Grumpkin curve. - -Fields support integer arithmetic and are often used as the default numeric type in Noir: - -```rust -fn main(x : Field, y : Field) { - let z = x + y; -} -``` - -`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new -private value `z` constrained to be equal to `x + y`. - -If proving efficiency is of priority, fields should be used as a default for solving problems. -Smaller integer types (e.g. `u64`) incur extra range constraints. - -### Integers - -An integer type is a range constrained field type. The Noir frontend currently supports unsigned, -arbitrary-sized integer types. - -An integer type is specified first with the letter `u`, indicating its unsigned nature, followed by -its length in bits (e.g. `32`). For example, a `u32` variable can store a value in the range of -$\\([0,2^{32}-1]\\)$: - -```rust -fn main(x : Field, y : u32) { - let z = x as u32 + y; -} -``` - -`x`, `y` and `z` are all private values in this example. However, `x` is a field while `y` and `z` -are unsigned 32-bit integers. If `y` or `z` exceeds the range $\\([0,2^{32}-1]\\)$, proofs created -will be rejected by the verifier. - -> **Note:** The default backend supports both even (e.g. `u16`, `u48`) and odd (e.g. `u5`, `u3`) -> sized integer types. - -### Booleans - -The `bool` type in Noir has two possible values: `true` and `false`: - -```rust -fn main() { - let t = true; - let f: bool = false; -} -``` - -> **Note:** When returning a boolean value, it will show up as a value of 1 for `true` and 0 for -> `false` in _Verifier.toml_. - -The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](./control_flow) and -[Assert Function](./assert) sections. - -### Strings - -The string type is a fixed length value defined with `str`. - -You can use strings in `assert()` functions or print them with -`std::println()`. - -```rust -fn main(message : pub str<11>, hex_as_string : str<4>) { - std::println(message); - assert(message == "hello world"); - assert(hex_as_string == "0x41"); -} -``` - -## Compound Types - -A compound type groups together multiple values into one type. Elements within a compound type can -be private or public. - -### Arrays - -An array is one way of grouping together values into one compound type. Array types can be inferred -or explicitly specified via the syntax `[; ]`: - -```rust -fn main(x : Field, y : Field) { - let my_arr = [x, y]; - let your_arr: [Field; 2] = [x, y]; -} -``` - -Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. - -Array elements can be accessed using indexing: - -```rust -fn main() { - let a = [1, 2, 3, 4, 5]; - - let first = a[0]; - let second = a[1]; -} -``` - -All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group -a `Field` value and a `u8` value together for example. - -You can write mutable arrays, like: - -```rust -fn main() { - let mut arr = [1, 2, 3, 4, 5]; - assert(arr[0] == 1); - - arr[0] = 42; - assert(arr[0] == 42); -} -``` - -You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. - -```rust -let array: [Field; 32] = [0; 32]; -``` - -#### Types - -You can create arrays of primitive types or structs. There is not yet support for nested arrays -(arrays of arrays) or arrays of structs that contain arrays. - -### Slices - -:::caution - -This feature is experimental. You should expect it to change in future versions, -cause unexpected behavior, or simply not work at all. - -::: - -A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. - -Slices are part of the [noir standard library](../standard_library/slice_methods) so you need to import the respective module in order to work with it. For example: - -```rust -use dep::std::slice; - -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -### Vectors - -:::caution - -This feature is experimental. You should expect it to change in future versions, -cause unexpected behavior, or simply not work at all. - -::: - -A vector is a collection type similar to Rust's Vector type. It's convenient way to use slices as mutable arrays. - -Example: - -```rust -use std::collections::vec::Vec; - -let mut vector: Vec = Vec::new(); -for i in 0..5 { - vector.push(i); -} -assert(vector.len() == 5); -``` - -### Tuples - -A tuple collects multiple values like an array, but with the added ability to collect values of -different types: - -```rust -fn main() { - let tup: (u8, u64, Field) = (255, 500, 1000); -} -``` - -One way to access tuple elements is via destructuring using pattern matching: - -```rust -fn main() { - let tup = (1, 2); - - let (one, two) = tup; - - let three = one + two; -} -``` - -Another way to access tuple elements is via direct member access, using a period (`.`) followed by -the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to -the second and so on: - -```rust -fn main() { - let tup = (5, 6, 7, 8); - - let five = tup.0; - let eight = tup.3; -} -``` - -### Structs - -A struct also allows for grouping multiple values of different types. Unlike tuples, we can also -name each field. - -> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the -> field type of Noir. - -Defining a struct requires giving it a name and listing each field within as `: ` pairs: - -```rust -struct Animal { - hands: Field, - legs: Field, - eyes: u8, -} -``` - -An instance of a struct can then be created with actual values in `: ` pairs in any -order. Struct fields are accessible using their given names: - -```rust -fn main() { - let legs = 4; - - let dog = Animal { - eyes: 2, - hands: 0, - legs, - }; - - let zero = dog.hands; -} -``` - -Structs can also be destructured in a pattern, binding each field to a new variable: - -```rust -fn main() { - let Animal { hands, legs: feet, eyes } = get_octopus(); - - let ten = hands + feet + eyes as u8; -} - -fn get_octopus() -> Animal { - let octopus = Animal { - hands: 0, - legs: 8, - eyes: 2, - }; - - octopus -} -``` - -The new variables can be bound with names different from the original struct field names, as -showcased in the `legs --> feet` binding in the example above. - -:::note -You can use Structs as inputs to the `main` function, but you can't output them -::: - -### Type Aliases - -A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: - -```rust -type Id = u8; - -fn main() { - let id: Id = 1; - let zero: u8 = 0; - assert(zero + 1 == id); -} -``` - -Type aliases can also be used with [generics](./06_generics.md): - -```rust -type Id = Size; - -fn main() { - let id: Id = 1; - let zero: u32 = 0; - assert(zero + 1 == id); -} -``` - -### BigInt - -You can acheive BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. - -## References - -Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. - -Example: - -```rust -fn main() { - let mut x = 2; - - // you can reference x as &mut and pass it to multiplyBy2 - multiplyBy2(&mut x); -} - -// you can access &mut here -fn multiplyBy2(x: &mut Field) { - // and dereference it with * - *x = *x * 2; -} -``` diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.9.0/language_concepts/01_functions.md deleted file mode 100644 index 54c618599d..0000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/01_functions.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Functions -description: - Learn how to declare functions and methods in Noir, a programming language with Rust semantics. - This guide covers parameter declaration, return types, call expressions, and more. -keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] ---- - -Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. - -To declare a function the `fn` keyword is used. - -```rust -fn foo() {} -``` - -All parameters in a function must have a type and all types are known at compile time. The parameter -is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. - -```rust -fn foo(x : Field, y : pub Field){} -``` - -The return type of a function can be stated by using the `->` arrow notation. The function below -states that the foo function must return a `Field`. If the function returns no value, then the arrow -is omitted. - -```rust -fn foo(x : Field, y : pub Field) -> Field { - x + y -} -``` - -Note that a `return` keyword is unneeded in this case - the last expression in a function's body is -returned. - -## Call Expressions - -Calling a function in Noir is executed by using the function name and passing in the necessary -arguments. - -Below we show how to call the `foo` function from the `main` function using a call expression: - -```rust -fn main(x : Field, y : Field) { - let z = foo(x); -} - -fn foo(x : Field) -> Field { - x + x -} -``` - -## Methods - -You can define methods in Noir on any struct type in scope. - -```rust -struct MyStruct { - foo: Field, - bar: Field, -} - -impl MyStruct { - fn new(foo: Field) -> MyStruct { - MyStruct { - foo, - bar: 2, - } - } - - fn sum(self) -> Field { - self.foo + self.bar - } -} - -fn main() { - let s = MyStruct::new(40); - assert(s.sum() == 42); -} -``` - -Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as -follows: - -```rust -assert(MyStruct::sum(s) == 42); -``` diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.9.0/language_concepts/02_control_flow.md deleted file mode 100644 index 691c514d9a..0000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/02_control_flow.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Control Flow -description: - Learn how to use loops and if expressions in the Noir programming language. Discover the syntax - and examples for for loops and if-else statements. -keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] ---- - -## Loops - -Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple -times. - -The following block of code between the braces is run 10 times. - -```rust -for i in 0..10 { - // do something -}; -``` - -## If Expressions - -Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required -for the statement's conditional to be surrounded by parentheses. - -```rust -let a = 0; -let mut x: u32 = 0; - -if a == 0 { - if a != 0 { - x = 6; - } else { - x = 2; - } -} else { - x = 5; - assert(x == 5); -} -assert(x == 2); -``` diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.9.0/language_concepts/03_ops.md deleted file mode 100644 index da02b12605..0000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/03_ops.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Logical Operations -description: - Learn about the supported arithmetic and logical operations in the Noir programming language. - Discover how to perform operations on private input types, integers, and booleans. -keywords: - [ - Noir programming language, - supported operations, - arithmetic operations, - logical operations, - predicate operators, - bitwise operations, - short-circuiting, - backend, - ] ---- - -# Operations - -## Table of Supported Operations - -| Operation | Description | Requirements | -| :-------- | :------------------------------------------------------------: | -------------------------------------: | -| + | Adds two private input types together | Types must be private input | -| - | Subtracts two private input types together | Types must be private input | -| \* | Multiplies two private input types together | Types must be private input | -| / | Divides two private input types together | Types must be private input | -| ^ | XOR two private input types together | Types must be integer | -| & | AND two private input types together | Types must be integer | -| \| | OR two private input types together | Types must be integer | -| << | Left shift an integer by another integer amount | Types must be integer | -| >> | Right shift an integer by another integer amount | Types must be integer | -| ! | Bitwise not of a value | Type must be integer or boolean | -| < | returns a bool if one value is less than the other | Upper bound must have a known bit size | -| <= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | -| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | -| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | -| == | returns a bool if one value is equal to the other | Both types must not be constants | -| != | returns a bool if one value is not equal to the other | Both types must not be constants | - -### Predicate Operators - -`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. -This differs from the operations such as `+` where the operands are used in _computation_. - -### Bitwise Operations Example - -```rust -fn main(x : Field) { - let y = x as u32; - let z = y & y; -} -``` - -`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise -`&`. - -> `x & x` would not compile as `x` is a `Field` and not an integer type. - -### Logical Operators - -Noir has no support for the logical operators `||` and `&&`. This is because encoding the -short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can -use the bitwise operators `|` and `&` which operate indentically for booleans, just without the -short-circuiting. - -```rust -let my_val = 5; - -let mut flag = 1; -if (my_val > 6) | (my_val == 0) { - flag = 0; -} -assert(flag == 1); - -if (my_val != 10) & (my_val < 50) { - flag = 0; -} -assert(flag == 0); -``` - -### Shorthand operators - -Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: - -```rust -let mut i = 0; -i = i + 1; -``` - -could be written as: - -```rust -let mut i = 0; -i += 1; -``` diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.9.0/language_concepts/04_assert.md deleted file mode 100644 index a25a946123..0000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/04_assert.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Assert Function -description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. -keywords: [Noir programming language, assert statement, predicate expression, comparison expression] ---- - -Noir includes a special `assert` function which will explicitly constrain the predicate/comparison -expression that follows to be true. If this expression is false at runtime, the program will fail to -be proven. - -### Example - -```rust -fn main(x : Field, y : Field) { - assert(x == y); -} -``` - -The above snippet compiles because `==` is a predicate operation. Conversely, the following will not -compile: - -```rust -// INCORRECT - -fn main(x : Field, y : Field) { - assert(x + y); -} -``` - -> The rationale behind this not compiling is due to ambiguity. It is not clear if the above should -> equate to `x + y == 0` or if it should check the truthiness of the result. diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.9.0/language_concepts/06_generics.md deleted file mode 100644 index 66f2e85e16..0000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/06_generics.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Generics -description: - Learn how to use Generics in Noir -keywords: [Noir, Rust, generics, functions, structs] ---- - -# Generics - -Generics allow you to use the same functions with multiple different concrete data types. You can -read more about the concept of generics in the Rust documentation -[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). - -Here is a trivial example showing the identity function that supports any type. In Rust, it is -common to refer to the most general type as `T`. We follow the same convention in Noir. - -```rust -fn id(x: T) -> T { - x -} -``` - -## In Structs - -Generics are useful for specifying types in structs. For example, we can specify that a field in a -struct will be of a certain generic type. In this case `value` is of type `T`. - -```rust -struct RepeatedValue { - value: T, - count: comptime Field, -} - -impl RepeatedValue { - fn new(value: T) -> Self { - Self { value, count: 1 } - } - - fn increment(mut repeated: Self) -> Self { - repeated.count += 1; - repeated - } - - fn print(self) { - for _i in 0 .. self.count { - dep::std::println(self.value); - } - } -} - -fn main() { - let mut repeated = RepeatedValue::new("Hello!"); - repeated = repeated.increment(); - repeated.print(); -} -``` - -The `print` function will print `Hello!` an arbitrary number of times, twice in this case. - -If we want to be generic over array lengths (which are type-level integers), we can use numeric -generics. Using these looks just like using regular generics, but these generics can resolve to -integers at compile-time, rather than resolving to types. Here's an example of a struct that is -generic over the size of the array it contains internally: - -```rust -struct BigInt { - limbs: [u32; N], -} - -impl BigInt { - // `N` is in scope of all methods in the impl - fn first(first: BigInt, second: BigInt) -> Self { - assert(first.limbs != second.limbs); - first - - fn second(first: BigInt, second: Self) -> Self { - assert(first.limbs != second.limbs); - second - } -} -``` - -## Calling functions on generic parameters - -Unlike Rust, Noir does not have traits, so how can one translate the equivalent of a trait bound in -Rust into Noir? That is, how can we write a function that is generic over some type `T`, while also -requiring there is a function like `eq: fn(T, T) -> bool` that works on the type? - -The answer is that we can translate this by passing in the function manually. Here's an example of -implementing array equality in Noir: - -```rust -fn array_eq(array1: [T; N], array2: [T; N], elem_eq: fn(T, T) -> bool) -> bool { - if array1.len() != array2.len() { - false - } else { - let mut result = true; - for i in 0 .. array1.len() { - result &= elem_eq(array1[i], array2[i]); - } - result - } -} - -fn main() { - assert(array_eq([1, 2, 3], [1, 2, 3], |a, b| a == b)); - - // We can use array_eq even for arrays of structs, as long as we have - // an equality function for these structs we can pass in - let array = [MyStruct::new(), MyStruct::new()]; - assert(array_eq(array, array, MyStruct::eq)); -} -``` - -You can see an example of generics in the tests -[here](https://github.com/noir-lang/noir/blob/master/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.9.0/language_concepts/07_mutability.md deleted file mode 100644 index 69798c7a27..0000000000 --- a/docs/versioned_docs/version-v0.9.0/language_concepts/07_mutability.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Mutability -description: - Learn about mutable variables, constants, and globals in Noir programming language. Discover how - to declare, modify, and use them in your programs. -keywords: [noir programming language, mutability in noir, mutable variables, constants, globals] ---- - -Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned -to via an assignment expression. - -```rust -let x = 2; -x = 3; // error: x must be mutable to be assigned to - -let mut y = 3; -let y = 4; // OK -``` - -The `mut` modifier can also apply to patterns: - -```rust -let (a, mut b) = (1, 2); -a = 11; // error: a must be mutable to be assigned to -b = 12; // OK - -let mut (c, d) = (3, 4); -c = 13; // OK -d = 14; // OK - -// etc. -let MyStruct { x: mut y } = MyStruct { x: a } -// y is now in scope -``` - -Note that mutability in noir is local and everything is passed by value, so if a called function -mutates its parameters then the parent function will keep the old value of the parameters. - -```rust -fn main() -> Field { - let x = 3; - helper(x); - x // x is still 3 -} - -fn helper(mut x: i32) { - x = 4; -} -``` - -## Comptime Values - -Comptime values are values that are known at compile-time. This is different to a witness -which changes per proof. If a comptime value that is being used in your program is changed, then your -circuit will also change. - -Comptime is slightly different from Rust's `const`. Namely, it is a bit more flexible in that normal functions can accept comptime parameters. For example, this is used to verify an array index is known at compile-time. Note that the "known at compile-time" here means "known after function inlining is performed while optimizing the program" and not "known during type-checking." - -Below we show how to declare a comptime value: - -```rust -fn main() { - let a: comptime Field = 5; - - // `comptime Field` can also be inferred: - let a = 5; -} -``` - -Comptime variables can be mutuable, but must be known at compile time: - -```rust -fn main(runtime_var: Field) -> pub Field { - let known_at_compile_time: comptime Field = 1; - - // The next line will cause an error - let bad_var: comptime Field = runtime_var; - -} -``` - -As `runtime_var` is a argument to the circuit it cannot be known at compile time and so assigning it to a comptime variable should fail. A circuit's arguments is the only way in which non-comptime variables can enter the circuit (excluding [brillig](./unconstrained) foreign calls). - -## Globals - -Noir also supports global variables. However, they must be compile-time variables. If `comptime` is -not explicitly written in the type annotation the compiler will implicitly specify the declaration -as compile-time. They can then be used like any other compile-time variable inside functions. The -global type can also be inferred by the compiler entirely. Globals can also be used to specify array -annotations for function parameters and can be imported from submodules. - -```rust -global N: Field = 5; // Same as `global N: comptime Field = 5` - -fn main(x : Field, y : [Field; N]) { - let res = x * N; - - assert(res == y[0]); - - let res2 = x * mysubmodule::N; - assert(res != res2); -} - -mod mysubmodule { - use dep::std; - - global N: Field = 10; - - fn my_helper() -> comptime Field { - let x = N; - x - } -} -``` - -## Why only local mutability? - -Witnesses in a proving system are immutable in nature. Noir aims to _closely_ mirror this setting -without applying additional overhead to the user. Modeling a mutable reference is not as -straightforward as on conventional architectures and would incur some possibly unexpected overhead. diff --git a/docs/versioned_docs/version-v0.9.0/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.9.0/modules_packages_crates/crates_and_packages.md deleted file mode 100644 index 34f28a7114..0000000000 --- a/docs/versioned_docs/version-v0.9.0/modules_packages_crates/crates_and_packages.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Crates and Packages -description: - Learn how to use Crates and Packages in your Noir project -keywords: [Nargo, dependencies, package management, crates, package] ---- - -## Crates - -A crate is the smallest amount of code that the Noir compiler considers at a time. -Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. - -### Crate Types - -A Noir crate can come in one of two forms: a binary crate or a library crate. - -_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. - -_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. - -### Crate Root - -Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. - -## Packages - -A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. - -A package _must_ contain either a library or a binary crate, but not both. - -### Differences from Cargo Packages - -One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. - -In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/docs/versioned_docs/version-v0.9.0/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.9.0/modules_packages_crates/dependencies.md deleted file mode 100644 index 2807ad5204..0000000000 --- a/docs/versioned_docs/version-v0.9.0/modules_packages_crates/dependencies.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Managing Dependencies -description: - Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub - and use them easily in your project. -keywords: [Nargo, dependencies, GitHub, package management, versioning] ---- - -Nargo allows you to upload packages to GitHub and use them as dependencies. - -## Specifying a dependency - -Specifying a dependency requires a tag to a specific commit and the git url to the url containing -the package. - -Currently, there are no requirements on the tag contents. If requirements are added, it would follow -semver 2.0 guidelines. - -> Note: Without a `tag` , there would be no versioning and dependencies would change each time you -> compile your project. - -For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: - -```toml -# Nargo.toml - -[dependencies] -ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} -``` - -## Specifying a local dependency - -You can also specify dependencies that are local to your machine. - -For example, this file structure has a library and binary crate - -``` -├── binary_crate -│   ├── Nargo.toml -│   └── src -│   └── main.nr -└── liba - ├── Nargo.toml - └── src - └── lib.nr -``` - -Inside of the binary crate, you can specify: - -```toml -# Nargo.toml - -[dependencies] -libA = { path = "../liba" } -``` - -## Importing dependencies - -You can import a dependency to a Noir file using the following syntax. For example, to import the -ecrecover-noir library and local liba referenced above: - -```rust -use dep::ecrecover; -use dep::libA; -``` - -You can also import only the specific parts of dependency that you want to use, like so: - -```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base; -``` - -Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you -can import multiple items in the same line by enclosing them in curly braces: - -```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; -``` - -## Dependencies of Dependencies - -Note that when you import a dependency, you also get access to all of the dependencies of that package. - -For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: - -```rust -use dep::phy_vector; - -fn main(x : Field, y : pub Field) { - //... - let f = phy_vector::fraction::toFraction(true, 2, 1); - //... -} -``` - -## Available Libraries - -Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). - -Some libraries that are available today include: - -- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library -- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) -- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers -- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address -- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees -- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir -- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/docs/versioned_docs/version-v0.9.0/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.9.0/modules_packages_crates/modules.md deleted file mode 100644 index e429b33651..0000000000 --- a/docs/versioned_docs/version-v0.9.0/modules_packages_crates/modules.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Understanding Modules -description: - Learn how to organize your files using modules in Noir, following the same convention as Rust's - module system. Examples included. -keywords: [Noir, Rust, modules, organizing files, sub-modules] ---- - -# Modules - -Noir's module system follows the same convention as the _newer_ version of Rust's module system. - -## Purpose of Modules - -Modules are used to organise files. Without modules all of your code would need to live in a single -file. In Noir, the compiler does not automatically scan all of your files to detect modules. This -must be done explicitly by the developer. - -## Examples - -### Importing a module in the crate root - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::hello_world(); -} -``` - -Filename : `src/foo.nr` - -```rust -fn from_foo() {} -``` - -In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module -declaration `mod foo` which prompts it to look for a foo.nr file. - -Visually this module hierarchy looks like the following : - -``` -crate - ├── main - │ - └── foo - └── from_foo - -``` - -### Importing a module throughout the tree -All modules are accessible from the ``crate::`` namespace. - -``` -crate - ├── bar - ├── foo - └── main - -``` -In the above snippet, if ``bar`` would like to use functions in ``foo``, it can do so by ``use crate::foo::function_name``. - -### Sub-modules - -Filename : `src/main.nr` - -```rust -mod foo; - -fn main() { - foo::from_foo(); -} -``` - -Filename : `src/foo.nr` - -```rust -mod bar; -fn from_foo() {} -``` - -Filename : `src/foo/bar.nr` - -```rust -fn from_bar() {} -``` - -In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule -of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the -compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` - -Visually the module hierarchy looks as follows: - -``` -crate - ├── main - │ - └── foo - ├── from_foo - └── bar - └── from_bar -``` diff --git a/docs/versioned_docs/version-v0.9.0/nargo/01_commands.md b/docs/versioned_docs/version-v0.9.0/nargo/01_commands.md deleted file mode 100644 index d550e13725..0000000000 --- a/docs/versioned_docs/version-v0.9.0/nargo/01_commands.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: Commands -description: - Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, - generate Solidity verifier smart contract and compile into JSON file containing ACIR - representation and ABI of circuit. -keywords: - [ - Nargo, - Noir CLI, - Noir Prover, - Noir Verifier, - generate Solidity verifier, - compile JSON file, - ACIR representation, - ABI of circuit, - TypeScript, - ] ---- - -## General options - -``` -Options: - -s, --show-ssa Emit debug information for the intermediate SSA IR - -d, --deny-warnings Quit execution when warnings are emitted - -h, --help Print help -``` - -## `nargo help [subcommand]` - -Prints the list of available commands or specific information of a subcommand. - -_Arguments_ - -- `` - The subcommand whose help message to display - -## `nargo check` - -Generate the `Prover.toml` and `Verifier.toml` files for specifying prover and verifier in/output -values of the Noir program respectively. - -## `nargo codegen-verifier` - -Generate a Solidity verifier smart contract for the program. - -## `nargo compile ` - -Compile the program into a JSON build artifact file containing the ACIR representation and the ABI -of the circuit. This build artifact can then be used to generate and verify proofs. - -You can also use "build" as an alias for compile. - -For example, `nargo build `. - -_Arguments_ - -- `` - The name of the circuit file - -_Options_ - -- `-c, --contracts` - Compile each contract function used within the program -- `--print-acir` - Displays the ACIR for the compiled circuit - -## `nargo new [path]` - -Creates a new Noir project in a new folder called `` - Name of the package -- `[path]` - The path to save the new project - -## `nargo init` - -Creates a new Noir project in the current directory. - -## `nargo execute [witness_name]` - -Runs the Noir program and prints its return value. - -_Arguments_ - -- `[witness_name]` - The name of the witness - -_Usage_ - -The inputs to the circuit are read from the `Prover.toml` file generated by `nargo check`, which -must be filled in. - -To save the witness to file, run the command with a value for the `witness-name` argument. A -`.tr` file will then be saved in the `build` folder. - -> **Info:** The `.tr` file is the witness file. The witness file can be considered as program inputs -> parsed for your program's ACIR. -> -> This file can be passed along with circuit's ACIR into a TypeScript project for proving and -> verification. See the [TypeScript](../typescript#proving-and-verifying-externally-compiled-files) -> section to learn more. - -## `nargo prove ` - -Creates a proof for the program. - -_Arguments_ - -- `` - The name of the proof - -_Options_ - -- `-v, --verify` - Verify proof after proving - -## `nargo verify ` - -Given a proof and a program, verify whether the proof is valid. - -_Arguments_ - -- `` - The proof to verify - -## `nargo test ` - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -See an example on the [testing page](./testing). - -_Arguments_ - -- `` - a pattern to indicate to only run tests with names containing the pattern - -## `nargo gates` - -Counts the occurrences of different gates in circuit - -## `nargo lsp` - -Start a long-running Language Server process that communicates over stdin/stdout. -Usually this command is not run by a user, but instead will be run by a Language Client, such as [vscode-noir](https://github.com/noir-lang/vscode-noir). diff --git a/docs/versioned_docs/version-v0.9.0/nargo/02_testing.md b/docs/versioned_docs/version-v0.9.0/nargo/02_testing.md deleted file mode 100644 index ba0bebd658..0000000000 --- a/docs/versioned_docs/version-v0.9.0/nargo/02_testing.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Testing in Noir -description: Learn how to use Nargo to test your Noir program in a quick and easy way -keywords: [Nargo, testing, Noir, compile, test] ---- - -You can test your Noir programs using Noir circuits. - -Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if -you run `nargo test`. - -For example if you have a program like: - -```rust -fn add(x: u64, y: u64) -> u64 { - x + y -} -#[test] -fn test_add() { - assert(add(2,2) == 4); - assert(add(0,1) == 1); - assert(add(1,0) == 1); -} -``` - -Running `nargo test` will test that the `test_add` function can be executed while satisfying the all -the contraints which allows you to test that add returns the expected values. Test functions can't -have any arguments currently. - -This is much faster compared to testing in Typescript but the only downside is that you can't -explicitly test that a certain set of inputs are invalid. i.e. you can't say that you want -add(2^64-1, 2^64-1) to fail. diff --git a/docs/versioned_docs/version-v0.9.0/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.9.0/nargo/03_solidity_verifier.md deleted file mode 100644 index 9ac60cb0ba..0000000000 --- a/docs/versioned_docs/version-v0.9.0/nargo/03_solidity_verifier.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Solidity Verifier -description: - Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier - contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart - contract. Read more to find out! -keywords: - [ - solidity verifier, - smart contract, - blockchain, - compiler, - plonk_vk.sol, - EVM blockchain, - verifying Noir programs, - proving backend, - Barretenberg, - ] ---- - -For certain applications, it may be desirable to run the verifier as a smart contract instead of on -a local machine. - -Compile a Solidity verifier contract for your Noir program by running: - -```sh -nargo codegen-verifier -``` - -A new `contract` folder would then be generated in your project directory, containing the Solidity -file `plonk_vk.sol`. It can be deployed on any EVM blockchain acting as a verifier smart contract. - -> **Note:** It is possible to compile verifier contracts of Noir programs for other smart contract -> platforms as long as the proving backend supplies an implementation. -> -> Barretenberg, the default proving backend for Nargo, supports compilation of verifier contracts in -> Solidity only for the time being. - -## Verify - -To verify a proof using the Solidity verifier contract, call the `verify` function with the -following signature: - -```solidity -function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) -``` - -You can see an example of how the `verify` function is called in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): - -```solidity -function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { - // ... - bytes32[] memory publicInputs = new bytes32[](4); - publicInputs[0] = merkleRoot; - publicInputs[1] = bytes32(proposalId); - publicInputs[2] = bytes32(vote); - publicInputs[3] = nullifierHash; - require(verifier.verify(proof, publicInputs), "Invalid proof"); -``` - -### Public Inputs - -:::tip - -A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in -Noir. - -Under the hood, the return value is passed as an input to the circuit and is checked at the end of -the circuit program. - -::: - -The verifier contract uses the output (return) value of a Noir program as a public input. So if you -have the following function - -```rust -fn main( - // Public inputs - pubkey_x: pub Field, - pubkey_y: pub Field, - // Private inputs - priv_key: Field, -) -> pub Field -``` - -then `verify` in `plonk_vk.sol` will expect 3 public inputs. Passing two inputs will result in an -error like `Reason: PUBLIC_INPUT_COUNT_INVALID(3, 2)`. - -In this case the 3 inputs to `verify` would be ordered as `[pubkey_x, pubkey_y, return]`. - -#### Struct inputs - -Consider the following program: - -```rust -struct Type1 { - val1: Field, - val2: Field, -} - -struct Nested { - t1: Type1, - is_true: bool, -} - -fn main(x: pub Field, nested: pub Nested, y: pub Field) { - //... -} -``` - -Structs will be flattened so that the array of inputs is 1-dimensional array. The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` - -## Noir for EVM chains - -You can currently deploy the Solidity verifier contracts to most EVM compatible chains. EVM chains that have been tested and are known to work include: - -- Optimism -- Arbitrum -- Polygon PoS -- Scroll -- Celo - -Other EVM chains should work, but have not been tested directly by our team. If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. - -### Unsupported chains - -Unfortunately not all "EVM" chains are supported. - -**zkSync** and the **Polygon zkEVM** do _not_ currently support proof verification via Solidity verifier contracts. They are missing the bn256 precompile contract that the verifier contract requires. Once these chains support this precompile, they may work. diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.9.0/standard_library/black_box_fns.md deleted file mode 100644 index c758846b68..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/black_box_fns.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Black Box Functions -description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. -keywords: [noir, black box functions] ---- - -Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. - -:::warning - -It is likely that not all backends will support a particular black box function. - -::: - -Because it is not guaranteed that all backends will support black box functions, it is possible that certain Noir programs won't compile against a particular backend if they use an unsupported black box function. It is possible to fallback to less efficient implementations written in Noir/ACIR in some cases. - -Black box functions are specified with the `#[foreign(black_box_fn)]` attribute. For example, the SHA256 function in the Noir [source code](https://github.com/noir-lang/noir/blob/v0.5.1/noir_stdlib/src/hash.nr) looks like: - -```rust -#[foreign(sha256)] -fn sha256(_input : [u8; N]) -> [u8; 32] {} -``` - -## Function list - -Here is a list of the current black box functions that are supported by UltraPlonk: - -- AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen](./cryptographic_primitives/hashes#pedersen) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) -- AND -- XOR -- RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) - -Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. - -You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/acvm/blob/acir-v0.12.0/acir/src/circuit/black_box_functions.rs). diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives.md deleted file mode 100644 index 2df4f92947..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Cryptographic primitives in Noir -description: - Learn about the cryptographic primitives ready to use for any Noir project -keywords: - [ - cryptographic primitives, - Noir project, - ] ---- - -The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. - -Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/00_hashes.mdx deleted file mode 100644 index 31a84cdb75..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/00_hashes.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Hash methods -description: - Learn about the cryptographic primitives ready to use for any Noir project, including sha256, - blake2s, pedersen, mimc_bn254 and mimc -keywords: - [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## sha256 - -Given an array of bytes, returns the resulting sha256 hash. - -```rust -fn sha256(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::sha256(x); -} -``` - - - -## blake2s - -Given an array of bytes, returns an array with the Blake2 hash - -```rust -fn blake2s(_input : [u8]) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::blake2s(x); -} -``` - - - -## pedersen - -Given an array of Fields, returns the Pedersen hash. - -```rust -fn pedersen(_input : [Field]) -> [Field; 2] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::pedersen(x); -} -``` - - - -## keccak256 - -Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes -(`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes -of the input. - -```rust -fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] -``` - -example: - -```rust -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let message_size = 4; - let hash = std::hash::keccak256(x, message_size); -} -``` - - - -## poseidon - -Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify -how many inputs are there to your Poseidon function. - -```rust -// example for hash_1, hash_2 accepts an array of length 2, etc -fn hash_1(input: [Field; 1]) -> Field -``` - -example: - -```rust -fn main() -{ - let hash1 = std::hash::poseidon::bn254::hash_2([1, 2]); - assert(hash1 == 0x115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a); -} -``` - -## mimc_bn254 and mimc - -`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by -providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if -you're willing to input your own constants: - -```rust -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field -``` - -otherwise, use the `mimc_bn254` method: - -```rust -fn mimc_bn254(array: [Field; N]) -> Field -``` - -example: - -```rust - -fn main() { - let x = [163, 117, 178, 149] // some random bytes - let hash = std::hash::mimc_bn254(x); -} -``` - -## hash_to_field - -```rust -fn hash_to_field(_input : [Field; N]) -> Field {} -``` - -Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return -a value which can be represented as a `Field`. - - diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/01_scalar.mdx deleted file mode 100644 index 62265cddb1..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/01_scalar.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Scalar multiplication -description: - See how you can perform scalar multiplications over a fixed base in Noir -keywords: - [ - cryptographic primitives, - Noir project, - scalar multiplication, - ] ---- - -import BlackBoxInfo from './common/\_blackbox.mdx'; - -## scalar_mul::fixed_base - -Performs scalar multiplication over the embedded curve whose coordinates are defined by the -configured noir field. For the BN254 scalar field, this is BabyJubJub or Grumpkin. - -```rust -fn fixed_base(_input : Field) -> [Field; 2] -``` - -example - -```rust -fn main(x : Field) { - let scal = std::scalar_mul::fixed_base(x); - std::println(scal); -} -``` - - diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/02_schnorr.mdx deleted file mode 100644 index 0e219c0e5f..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/02_schnorr.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Schnorr Signatures -description: Learn how you can verify Schnorr signatures using Noir -keywords: [cryptographic primitives, Noir project, schnorr, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## schnorr::verify_signature - -Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). - -```rust -fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8]) -> bool -``` - -where `_signature` can be generated like so using the npm package -[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) - -```js -const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); -const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); - -... - -const barretenberg = await BarretenbergWasm.new(); -const schnorr = new Schnorr(barretenberg); -const pubKey = schnorr.computePublicKey(privateKey); -const message = ... -const signature = Array.from( - schnorr.constructSignature(hash, privateKey).toBuffer() -); - -... -``` - - diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx deleted file mode 100644 index 3934a0338d..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: ECDSA Signature Verification -description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves -keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. - -## ecdsa_secp256k1::verify_signature - -Verifier for ECDSA Secp256k1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - -## ecdsa_secp256r1::verify_signature - -Verifier for ECDSA Secp256r1 signatures - -```rust -fn verify_signature(_public_key_x : [u8; 32], _public_key_y : [u8; 32], _signature: [u8; 64], _message: [u8]) -> bool -``` - -example: - -```rust -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { - let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} -``` - - diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/05_eddsa.mdx deleted file mode 100644 index 8f060ed331..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/05_eddsa.mdx +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: EdDSA Verification -description: Learn about the cryptographic primitives regarding EdDSA -keywords: [cryptographic primitives, Noir project, eddsa, signatures] ---- - -import BlackBoxInfo from './common/_blackbox.mdx'; - -## eddsa::eddsa_poseidon_verify - -Verifier for EdDSA signatures - -```rust -fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool -``` - - diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/common/_blackbox.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/common/_blackbox.mdx deleted file mode 100644 index 9fe9b48fbf..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/common/_blackbox.mdx +++ /dev/null @@ -1,5 +0,0 @@ -:::info - -This is a black box function. Read [this section](../black_box_fns) to learn more about black box functions in Noir. - -::: \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md b/docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md deleted file mode 100644 index 4d1cdc953e..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Field Methods -description: - Learn about common methods on Noir Field, including to_le_bits, to_le_bytes, to_le_radix, - to_be_radix, pow_32, etc, and see code examples. -keywords: - [ - Noir Field, - to_le_bits, - to_le_bytes, - to_le_radix, - to_be_radix, - pow_32, - Little Endian, - Big Endian, - Vector, - Exponent, - ] ---- - -After declaring a Field, you can use these common methods on it: - -## to_le_bits - -Transforms the field into an array of bits, Little Endian. - -```rust -fn to_le_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2 - let bits = field.to_le_bits(32); -} -``` - -## to_be_bits - -Transforms the field into an array of bits, Big Endian. - -```rust -fn to_be_bits(_x : Field, _bit_size: u32) -> [u1; N] -``` - -example: - -```rust -fn main() { - let field = 2 - let bits = field.to_be_bits(32); -} -``` - -## to_le_bytes - -Transforms into an array of bytes, Little Endian - -```rust -fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let bytes = field.to_le_bytes(4); -} -``` - -## to_be_bytes - -Transforms into an array of bytes, Big Endian - -```rust -fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let bytes = field.to_be_bytes(4); -} -``` - -## to_le_radix - -Decomposes into a vector over the specified base, Little Endian - -```rust -fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let radix = field.to_le_radix(256, 4); -} -``` - -## to_be_radix - -Decomposes into a vector over the specified base, Big Endian - -```rust -fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] -``` - -example: - -```rust -fn main() { - let field = 2 - let radix = field.to_be_radix(256, 4); -} -``` - -## pow_32 - -Returns the value to the power of the specified exponent - -```rust -fn pow_32(self, exponent: Field) -> Field -``` - -example: - -```rust -fn main() { - let field = 2 - let pow = field.pow_32(4); - assert(pow == 16); -} -``` - -## sgn0 - -Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1. - -```rust -fn sgn0(self) -> u1 -``` diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/logging.md b/docs/versioned_docs/version-v0.9.0/standard_library/logging.md deleted file mode 100644 index 42a84be199..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/logging.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Logging -description: - Learn how to use the println statement for debugging in Noir with this tutorial. Understand the - basics of logging in Noir and how to implement it in your code. -keywords: - [ - noir logging, - println statement, - debugging in noir, - noir std library, - logging tutorial, - basic logging in noir, - noir logging implementation, - noir debugging techniques, - rust, - ] ---- - -# Logging - -The standard library provides a familiar `println` statement you can use. Despite being a limited -implementation of rust's `println!` macro, this construct can be useful for debugging. - -The `println` statement is unconstrained, so it works for outputting integers, fields, strings, and even structs or expressions. For example: - -```rust -use dep::std; - -struct Person { - age : Field, - height : Field, -} - -fn main(age : Field, height : Field) { - let person = Person { age : age, height : height }; - std::println(person); - std::println(age + height); - std::println("Hello world!"); -} - -``` diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.9.0/standard_library/merkle_trees.md deleted file mode 100644 index 57d8c4a9e4..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/merkle_trees.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Merkle Trees -description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. -keywords: - [ - Merkle trees in Noir, - Noir programming language, - check membership, - computing root from leaf, - Noir Merkle tree implementation, - Merkle tree tutorial, - Merkle tree code examples, - Noir libraries, - pedersen hash., - ] ---- - -## compute_merkle_root - -Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](cryptographic_primitives/00_hashes.mdx#pedersen). - -```rust -fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field -``` - -example: - -```rust -/** - // these values are for this example only - index = "0" - priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" - secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" - note_hash_path = [ - "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", - "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", - "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" - ] - */ -fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { - - let pubkey = std::scalar_mul::fixed_base(priv_key); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y, secret]); - - let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path); - std::println(root); -} -``` - -To check merkle tree membership: - -1. Include a merkle root as a program input. -2. Compute the merkle root of a given leaf, index and hash path. -3. Assert the merkle roots are equal. - -For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/recursion.md b/docs/versioned_docs/version-v0.9.0/standard_library/recursion.md deleted file mode 100644 index 4705ae6c57..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/recursion.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -title: Recursive Proofs -description: Learn about how to write recursive proofs in Noir. -keywords: [recursion, recursive proofs, verification_key, aggregation object, verify_proof] ---- - -Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. - -The `verify_proof` function takes a verification key, proof and public inputs for a zk program, as well as a key hash and an input aggregation object. The key hash is used to check the validity of the verification key and the input aggregation object is required by some proving systems. The `verify_proof` function returns an output aggregation object that can then be fed into future iterations of the proof verification if required. - -```rust -#[foreign(verify_proof)] -fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : Field, _key_hash : Field, _input_aggregation_object : [Field]) -> [Field] {} -``` - -:::info - -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. - -::: - -## Aggregation Object - -The purpose of the input aggregation object is a little less clear though (and the output aggregation object that is returned from the `std::verify_proof` method). Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. In the case of PLONK the recursive aggregation object is two G1 points (expressed as 16 witness values). The final verifier (in our case this is most often the smart contract verifier) has to be aware of this aggregation object to execute a pairing and check the validity of these points (thus completing the recursive verification). - -So for example in this circuit: - -```rust -use dep::std; - -fn main( - verification_key : [Field; 114], - proof : [Field; 94], - public_inputs : [Field; 1], - key_hash : Field, - input_aggregation_object : [Field; 16], - proof_b : [Field; 94], -) -> pub [Field; 16] { - let output_aggregation_object_a = std::verify_proof( - verification_key, - proof, - public_inputs, - key_hash, - input_aggregation_object - ); - - let output_aggregation_object = std::verify_proof( - verification_key, - proof_b, - public_inputs, - key_hash, - output_aggregation_object_a - ); - - let mut output = [0; 16]; - for i in 0..16 { - output[i] = output_aggregation_object[i]; - } - output -} -``` - -In this example we have a circuit, that generates proofs A and B, that is being verified in circuit C. Assuming that the proof being passed in is not already a recursive proof, the `input_aggregation_object` will be all zeros. It will then generate an `output_aggregation_object`. This blob of data then becomes the `input_aggregation_object` of the next recursive aggregation we wish to compute. We can see here as the same public inputs, verification key, and key hash are used that we are verifying two proofs generated from the same circuit in this single circuit. `std::verify_proof` returns a `[Field]` because the size of an aggregation object is proof system dependent--in barretenberg, aggregation objects are two G1 points, while in Halo2, the aggregation object is a list of G1 points that is log the circuit size. So for the final step we convert the slice into an array of size 16 because we are generating proofs using UltraPlonk. - -## Parameters - -### `verification_key` - -The verification key for the zk program that is being verified. - -### `proof` - -The proof for the zk program that is being verified. - -### `public_inputs` - -These represent the public inputs of the proof we are verifying. They should be checked against in the circuit after construction of a new aggregation state. - -### `key_hash` - -A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. - -### `input_aggregation_object` - -An aggregation object is blob of data that the top-level verifier must run some proof system specific algorithm on to complete verification. The size is proof system specific and will be set by the backend integrating this opcode. The input aggregation object is only not `None` when we are verifying a previous recursive aggregation in the current circuit. If this is the first recursive aggregation there is no input aggregation object. It is left to the backend to determine how to handle when there is no input aggregation object. - -## Return value - -### `output_aggregation_object` - -This is the result of a recursive aggregation and is what will be fed into the next verifier. -The next verifier can either perform a final verification (returning true or false) or perform another recursive aggregation where this output aggregation object will be the input aggregation object of the next recursive aggregation. - -## Example - -You can see an example of how to do recursive proofs in [this example recursion demo repo](https://github.com/Savio-Sou/recursion-demo/tree/main). diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/slice_methods.md b/docs/versioned_docs/version-v0.9.0/standard_library/slice_methods.md deleted file mode 100644 index 8b93d8ea42..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/slice_methods.md +++ /dev/null @@ -1,279 +0,0 @@ ---- -title: Slice Methods -description: - Learn about the commonly used methods available for slices in Noir, including push_back, len, srt, map, fold, reduce, all, and any. -keywords: [rust, slice, methods, push_back, len, sort, fold, reduce, all, any] ---- - -For convenience, the STD provides some ready-to-use, common methods for slices: - -## push_back - -Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. - -```rust -fn push_back(_self: [T], _elem: T) -> [T] -``` - -example: - -```rust -fn main() -> pub Field { - let mut slice: [Field] = [0; 2]; - - let mut new_slice = slice.push_back(6); - new_slice.len() -} -``` - -View the corresponding test file [here][test-file]. - -## push_front - -Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. - -```rust -fn push_front(_self: Self, _elem: T) -> Self -``` - -Example: - -```rust -let mut new_slice: [Field] = []; -new_slice = new_slice.push_front(20); -assert(new_slice[0] == 20); // returns true -``` - -View the corresponding test file [here][test-file]. - -## pop_front - -Returns a tuple of two items, the first element of the array and the rest of the array. - -```rust -fn pop_front(_self: Self) -> (T, Self) -``` - -Example: - -```rust -let (first_elem, rest_of_slice) = slice.pop_front(); -``` - -View the corresponding test file [here][test-file]. - -## pop_back - -Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. - -```rust -fn pop_back(_self: Self) -> (Self, T) -``` - -Example: - -```rust -let (popped_slice, last_elem) = slice.pop_back(); -``` - -View the corresponding test file [here][test-file]. - -## insert - -Inserts an element at a specified index and shifts all following elements by 1. - -```rust -fn insert(_self: Self, _index: Field, _elem: T) -> Self -``` - -Example: - -```rust - new_slice = rest_of_slice.insert(2, 100); -assert(new_slice[2] == 100); -``` - -View the corresponding test file [here][test-file]. - -## remove - -Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. - -```rust -fn remove(_self: Self, _index: Field) -> (Self, T) -``` - -Example: - -```rust -let (remove_slice, removed_elem) = slice.remove(3); -``` - -View the corresponding test file [here]([test-file]. - -## len - -Returns the length of a slice - -```rust -fn len(_slice: [T]) -> comptime Field -``` - -Example: - -```rust -fn main() { - let slic = [42, 42] - assert(slic.len() == 2); -} -``` - -## sort - -Returns a new sorted slice. The original slice remains untouched. Notice that this function will -only work for slices of fields or integers, not for any arbitrary type. This is because the sorting -logic the function uses internally is optimized specifically for these values. If you need a sort function to -sort any type, you should use the function `sort_via` described below. - -```rust -fn sort(_slice: [T]) -> [T] -``` - -Example: - -```rust -fn main() { - let slic = [42, 32] - let sorted = slic.sort(); - assert(sorted == [32, 42]); -} -``` - -## sort_via - -Sorts the slice with a custom comparison function - -```rust -fn sort_via(mut a: [T], ordering: fn(T, T) -> bool) -> [T] -``` - -Example: - -```rust -fn main() { - let slic = [42, 32] - let sorted_ascending = slic.sort_via(|a, b| a < b); - assert(sorted_ascending == [32, 42]); // verifies - - let sorted_descending = slic.sort_via(|a, b| a > b); - assert(sorted_descending == [32, 42]); // does not verify -} -``` - -## map - -Applies a function to each element of the slice, returning a new slice containing the mapped elements. - -```rust -fn map(f: fn(T) -> U) -> [U] -``` - -Example: - -```rust -let a = [1, 2, 3]; -let b = a.map(|a| a * 2) // b is now [2, 4, 6] -``` - -## fold - -Applies a function to each element of the slice, returning the final accumulated value. The first -parameter is the initial value. - -```rust -fn fold(mut accumulator: U, f: fn(U, T) -> U) -> U -``` - -This is a left fold, so the given function will be applied to the accumulator and first element of -the slice, then the second, and so on. For a given call the expected result would be equivalent to: - -```rust -let a1 = [1]; -let a2 = [1, 2]; -let a3 = [1, 2, 3]; - -let f = |a, b| a - b; -a1.fold(10, f) //=> f(10, 1) -a2.fold(10, f) //=> f(f(10, 1), 2) -a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) -``` - -Example: - -```rust - -fn main() { - let slic = [2,2,2,2,2] - let folded = slic.fold(0, |a, b| a + b); - assert(folded == 10); -} - -``` - -## reduce - -Same as fold, but uses the first element as starting element. - -```rust -fn reduce(f: fn(T, T) -> T) -> T -``` - -Example: - -```rust -fn main() { - let slic = [2,2,2,2,2] - let reduced = slic.reduce(|a, b| a + b); - assert(reduced == 10); -} -``` - -## all - -Returns true if all the elements satisfy the given predicate - -```rust -fn all(predicate: fn(T) -> bool) -> bool -``` - -Example: - -```rust -fn main() { - let slic = [2,2,2,2,2] - let all = slic.all(|a| a == 2); - assert(all); -} -``` - -## any - -Returns true if any of the elements satisfy the given predicate - -```rust -fn any(predicate: fn(T) -> bool) -> bool -``` - -Example: - -```rust -fn main() { - let slic = [2,2,2,2,5] - let any = slic.any(|a| a == 5); - assert(any); -} - -``` - -[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr - diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/zeroed.md b/docs/versioned_docs/version-v0.9.0/standard_library/zeroed.md deleted file mode 100644 index 97dab02dac..0000000000 --- a/docs/versioned_docs/version-v0.9.0/standard_library/zeroed.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Zeroed Function -description: - The zeroed function returns a zeroed value of any type. -keywords: - [ - zeroed - ] ---- - -Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. - -You can access the function at `std::unsafe::zeroed`. - -This function currently supports the following types: - -- Field -- Bool -- Uint -- Array -- String -- Tuple -- Function - -Using it on other types could result in unexpected behavior. diff --git a/docs/versioned_docs/version-v0.9.0/typescript.md b/docs/versioned_docs/version-v0.9.0/typescript.md deleted file mode 100644 index 8608783784..0000000000 --- a/docs/versioned_docs/version-v0.9.0/typescript.md +++ /dev/null @@ -1,243 +0,0 @@ ---- -title: Working with TypeScript -description: - Learn how to interact with Noir programs using TypeScript. Follow this tutorial to compile your - program, specify inputs, initialize a prover & verifier, and prove and verify your program. -keywords: [TypeScript, Noir, tutorial, compile, inputs, prover, verifier, proof] ---- - -Interactions with Noir programs can also be performed in TypeScript, which can come in handy when -writing tests or when working in TypeScript-based projects like [Hardhat](https://hardhat.org/). - -You can check the complete code for this tutorial here: [browser with next.js](https://github.com/signorecello/noir-min-browser-example) and [node.js](https://github.com/signorecello/noir-min-nodejs-example). If you want just a browser boilerplate to start with, check out the [noir-starter](https://github.com/noir-lang/noir-starter) for an example implementation. - -:::note - -You may find unexpected errors working with some frameworks such as `vite`. This is due to the -nature of `wasm` files and the way Noir uses web workers. As we figure it out, we suggest using -[Create React App](https://create-react-app.dev/), or [Next.js](https://nextjs.org/) for a quick -start. - -::: - -## Setup - -Make sure you are using Noir version >= 0.10.1. - -You can check your current version by running `nargo --version`. - -You can install version 0.10.1 with noirup with - -```bash -noirup -v 0.10.1 -``` - -See the [Installation page](./getting_started/nargo_installation) for more info. - -We're assuming you're using ES6 and ESM for both browser (for example with React), or nodejs. Install [Node.js](https://nodejs.org/en). Init a new project with `npm init` and add `"type": "module"` to your `package.json`, to let `node` know we're using the new ESM sytem: - -```json -{ - "type": "module" - // the rest of your package.json -} -``` - -Install Noir dependencies in your project by running: - -```bash -npm i @aztec/bb.js@0.3.6 https://git@github.com/noir-lang/acvm-simulator-wasm.git#b9d9ca9dfc5140839f23998d9466307215607c42 fflate ethers@5.7.2 -``` - -This will install the `acvm-simulator` that will generate our witness, and the proving backend barretenberg `bb.js`. - -We're also installing `ethers` because we're too lazy to write a function that pads public inputs with 32bytes, and `fflate` to help us decompress our circuit bytecode. - -Since we're with typescript and using `nodejs` types, we also recommend to install the `@types/node` package, otherwise your IDE will scream at you. - -```bash -npm i --save-dev @types/node -``` - -:::note - -While Noir is in rapid development, some packages could interfere with others. For that reason, you -should use these specified versions. Let us know if for some reason you need to use other ones. - -::: - -As for the circuit, run `nargo init` to create a new Noir project. - -We will use a Standard Noir Example and place it in the `src` folder. This program simply multiplies input `x` with input `y` and returns the result `z`. The verifier doesn't know the value of `x`: we're proving that we know it without making it public. - -```rust -// src/main.nr -fn main(x: u32, y: pub u32) -> pub u32 { - let z = x * y; - z -} -``` - -One valid scenario for proving could be `x = 3`, `y = 4` and `return = 12` - -## Compiling - -In order to start proving, we need to compile our circuit into the intermediate representation used by our backend. As of today, you have to do that with `nargo`. Just hop to your circuits folder and run `nargo compile`. - -:::info - -At this time, you need to use a nightly version of nargo. Using [noirup](./getting_started/00_nargo_installation.md#option-1-noirup) you can do this simply by running `noirup -n`. - -::: - -You should have a `json` file in `target/` with your circuit's bytecode. The json file is name based on the project name specified in Nargo.toml, so for a project named "test", it will be at `target/test.json`. You can then import that file normally. - -```ts -import circuit from '../target/test.json' assert { type: 'json' }; -``` - -## Decompressing the circuit - -The compiled circuit comes compressed. We need to decompress it, that's where `fflate` comes in. - -```ts -import { decompressSync } from 'fflate'; - -const acirBuffer = Buffer.from(circuit.bytecode, 'base64'); -const acirBufferUncompressed = decompressSync(acirBuffer); -``` - -From here, it's highly recommended you store `acirBuffer` and `acirBufferUncompressed` close by, as they will be used for witness generation and proving. - -## Initializing ACVM and BB.JS - -:::note - -This step will eventually be abstracted away as Noir tooling matures. For now, you should be fine just literally copy-pasting most of this into your own code. - -::: - -Before proving, `bb.js` needs to be initialized. We need to import some functions and use them - -```ts -import { Crs, newBarretenbergApiAsync, RawBuffer } from '@aztec/bb.js/dest/node/index.js'; - -const api = await newBarretenbergApiAsync(4); - -const [exact, circuitSize, subgroup] = await api.acirGetCircuitSizes(acirBufferUncompressed); -const subgroupSize = Math.pow(2, Math.ceil(Math.log2(circuitSize))); -const crs = await Crs.new(subgroupSize + 1); -await api.commonInitSlabAllocator(subgroupSize); -await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data())); - -const acirComposer = await api.acirNewAcirComposer(subgroupSize); -``` - -We should take two very useful objects from here: `api` and `acirComposer`. Make sure to keep these close by! - -:::info - -On the browser, you also need to init the ACVM. You can do that by importing it and calling it like: - -```ts -import initACVM, { executeCircuit, compressWitness } from '@noir-lang/acvm_js'; - -await initACVM(); -// the rest of your code -``` - -::: - -## Generating witnesses - -Witness generation is what allows us to prove with arbitrary inputs (like user inputs on a form, game, etc). In this example, our input is a simple object with our circuit inputs `x`, `y`, and return `z` (fun fact: the return value in Noir is actually a public input!). We're wrapping it in a function, so it can be conveniently called later on. - -```ts -import { ethers } from 'ethers'; // I'm lazy so I'm using ethers to pad my input -import { executeCircuit, compressWitness } from '@noir-lang/acvm_js'; - -async function generateWitness(input: any, acirBuffer: Buffer): Promise { - const initialWitness = new Map(); - initialWitness.set(1, ethers.utils.hexZeroPad(`0x${input.x.toString(16)}`, 32)); - initialWitness.set(2, ethers.utils.hexZeroPad(`0x${input.y.toString(16)}`, 32)); - - const witnessMap = await executeCircuit(acirBuffer, initialWitness, () => { - throw Error('unexpected oracle'); - }); - - const witnessBuff = compressWitness(witnessMap); - return witnessBuff; -} -``` - -## Proving - -Finally, we're ready to prove with our backend. Just like with the witness generation, could be useful to wrap it in its own function: - -```ts -async function generateProof(witness: Uint8Array) { - const proof = await api.acirCreateProof( - acirComposer, - acirBufferUncompressed, - decompressSync(witness), - false, - ); - return proof; -} -``` - -## Verifying - -Our backend should also be ready to verify our proof: - -```ts -async function verifyProof(proof: Uint8Array) { - await api.acirInitProvingKey(acirComposer, acirBufferUncompressed); - const verified = await api.acirVerifyProof(acirComposer, proof, false); - return verified; -} -``` - -## Now for the fun part - -Let's call our functions, and destroy our API! - -```ts -const input = { x: 3, y: 4 }; -const witness = await generateWitness(input, acirBuffer); -console.log('Witness generated!'); -const proof = await generateProof(witness); -console.log('Proof generated!'); -await verifyProof(proof); -console.log('Proof verified!'); -api.destroy(); -``` - -You can use [this](https://gist.github.com/critesjosh/6f3ba19fdc9298b24e90ba4f736247dc) tsconfig.json. You can see the script [here](https://gist.github.com/critesjosh/4aa36e87a0cc3f09feaf1febb4d11348). - -## Verifying with Smart Contract - -Alternatively, a verifier smart contract can be generated and used for verifying Noir proofs in -TypeScript as well. - -This could be useful if the Noir program is designed to be decentrally verified and/or make use of -decentralized states and logics that is handled at the smart contract level. - -This assumes you've already ran `nargo codegen-verifier`, got your smart contract, and deployed it with Hardhat, Foundry, or your tool of choice. You can then verify a Noir proof by simply calling it. - -Currently, `bb.js` appends the public inputs to the proof. However, these inputs need to be fed separately to the verifier contract. A simple solution is to just slice them from the resulting proof, like this: - -```ts -import { ethers } from 'ethers'; // example using ethers v5 -import artifacts from '../artifacts/circuits/contract/plonk_vk.sol/UltraVerifier.json'; // I compiled using Hardhat, so I'm getting my abi from here - -const verifierAddress = '0x123455'; // your verifier address -const provider = new ethers.providers.Web3Provider(window.ethereum); -const signer = this.provider.getSigner(); - -const contract = new ethers.Contract(verifierAddress, artifacts.abi, signer); - -const publicInputs = proof.slice(0, 32); -const slicedProof = proof.slice(32); -await contract.verify(slicedProof, [publicInputs]); -``` diff --git a/docs/versioned_sidebars/version-v0.10.5-sidebars.json b/docs/versioned_sidebars/version-v0.10.5-sidebars.json deleted file mode 100644 index a51ebf8764..0000000000 --- a/docs/versioned_sidebars/version-v0.10.5-sidebars.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "category", - "label": "Data Types", - "link": { - "type": "doc", - "id": "language_concepts/data_types" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts/data_types" - } - ] - }, - "language_concepts/functions", - "language_concepts/control_flow", - "language_concepts/ops", - "language_concepts/assert", - "language_concepts/unconstrained", - "language_concepts/generics", - "language_concepts/mutability", - "language_concepts/lambdas", - "language_concepts/comments", - "language_concepts/distinct", - "language_concepts/shadowing" - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/recursion", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns", - "standard_library/options" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "doc", - "id": "typescript", - "label": "Working with Typescript" - } - ] -} diff --git a/docs/versioned_sidebars/version-v0.19.0-sidebars.json b/docs/versioned_sidebars/version-v0.19.0-sidebars.json new file mode 100644 index 0000000000..a9ec39925d --- /dev/null +++ b/docs/versioned_sidebars/version-v0.19.0-sidebars.json @@ -0,0 +1,141 @@ +{ + "sidebar": [ + { + "type": "doc", + "id": "index", + "label": "Noir" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "autogenerated", + "dirName": "getting_started" + } + ] + }, + { + "type": "category", + "label": "Examples", + "items": [ + { + "type": "autogenerated", + "dirName": "examples" + } + ] + }, + { + "type": "category", + "label": "Nargo", + "items": [ + { + "type": "autogenerated", + "dirName": "nargo" + } + ] + }, + { + "type": "category", + "label": "Language Concepts", + "items": [ + { + "type": "category", + "label": "Data Types", + "link": { + "type": "doc", + "id": "language_concepts/data_types" + }, + "items": [ + { + "type": "autogenerated", + "dirName": "language_concepts/data_types" + } + ] + }, + "language_concepts/functions", + "language_concepts/control_flow", + "language_concepts/ops", + "language_concepts/assert", + "language_concepts/unconstrained", + "language_concepts/generics", + "language_concepts/mutability", + "language_concepts/lambdas", + "language_concepts/comments", + "language_concepts/distinct", + "language_concepts/shadowing" + ] + }, + { + "type": "category", + "label": "Noir Standard Library", + "items": [ + { + "type": "category", + "label": "Cryptographic Primitives", + "link": { + "type": "doc", + "id": "standard_library/cryptographic_primitives" + }, + "items": [ + { + "type": "autogenerated", + "dirName": "standard_library/cryptographic_primitives" + } + ] + }, + "standard_library/recursion", + "standard_library/logging", + "standard_library/merkle_trees", + "standard_library/zeroed", + "standard_library/black_box_fns", + "standard_library/options" + ] + }, + { + "type": "category", + "label": "Modules, Packages and Crates", + "items": [ + { + "type": "autogenerated", + "dirName": "modules_packages_crates" + } + ] + }, + { + "type": "category", + "label": "NoirJS", + "link": { + "type": "doc", + "id": "noir_js/noir_js" + }, + "items": [ + { + "type": "category", + "label": "Guides", + "items": [ + { + "type": "autogenerated", + "dirName": "noir_js/getting_started" + } + ] + }, + { + "type": "category", + "label": "Reference", + "items": [ + { + "type": "autogenerated", + "dirName": "noir_js/reference" + } + ] + } + ] + }, + { + "type": "doc", + "id": "migration_notes", + "label": "Migration notes" + } + ] +} diff --git a/docs/versioned_sidebars/version-v0.19.3-sidebars.json b/docs/versioned_sidebars/version-v0.19.3-sidebars.json new file mode 100644 index 0000000000..6823055c5d --- /dev/null +++ b/docs/versioned_sidebars/version-v0.19.3-sidebars.json @@ -0,0 +1,288 @@ +{ + "sidebar": [ + { + "type": "doc", + "id": "index", + "label": "Noir" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "autogenerated", + "dirName": "getting_started" + } + ] + }, + { + "type": "category", + "label": "Examples", + "items": [ + { + "type": "autogenerated", + "dirName": "examples" + } + ] + }, + { + "type": "category", + "label": "Nargo", + "items": [ + { + "type": "autogenerated", + "dirName": "nargo" + } + ] + }, + { + "type": "category", + "label": "Language Concepts", + "items": [ + { + "type": "category", + "label": "Data Types", + "link": { + "type": "doc", + "id": "language_concepts/data_types" + }, + "items": [ + { + "type": "autogenerated", + "dirName": "language_concepts/data_types" + } + ] + }, + "language_concepts/functions", + "language_concepts/control_flow", + "language_concepts/ops", + "language_concepts/assert", + "language_concepts/unconstrained", + "language_concepts/generics", + "language_concepts/mutability", + "language_concepts/lambdas", + "language_concepts/comments", + "language_concepts/distinct", + "language_concepts/shadowing" + ] + }, + { + "type": "category", + "label": "Noir Standard Library", + "items": [ + { + "type": "category", + "label": "Cryptographic Primitives", + "link": { + "type": "doc", + "id": "standard_library/cryptographic_primitives" + }, + "items": [ + { + "type": "autogenerated", + "dirName": "standard_library/cryptographic_primitives" + } + ] + }, + "standard_library/recursion", + "standard_library/logging", + "standard_library/merkle_trees", + "standard_library/zeroed", + "standard_library/black_box_fns", + "standard_library/options" + ] + }, + { + "type": "category", + "label": "Modules, Packages and Crates", + "items": [ + { + "type": "autogenerated", + "dirName": "modules_packages_crates" + } + ] + }, + { + "type": "category", + "label": "NoirJS", + "link": { + "type": "doc", + "id": "noir_js/noir_js" + }, + "items": [ + { + "type": "category", + "label": "Guides", + "items": [ + { + "type": "autogenerated", + "dirName": "noir_js/getting_started" + } + ] + }, + { + "type": "category", + "label": "Reference", + "items": [ + { + "type": "category", + "label": "Noir JS", + "link": { + "type": "doc", + "id": "noir_js/reference/noir_js/index" + }, + "items": [ + { + "type": "category", + "label": "Classes", + "items": [ + { + "type": "doc", + "id": "noir_js/reference/noir_js/classes/Noir", + "label": "Noir" + } + ] + }, + { + "type": "category", + "label": "Type Aliases", + "items": [ + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/CompiledCircuit", + "label": "CompiledCircuit" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/ForeignCallHandler", + "label": "ForeignCallHandler" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/ForeignCallInput", + "label": "ForeignCallInput" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/ForeignCallOutput", + "label": "ForeignCallOutput" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/ProofData", + "label": "ProofData" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/WitnessMap", + "label": "WitnessMap" + } + ] + }, + { + "type": "category", + "label": "Functions", + "items": [ + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/and", + "label": "and" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/blake2s256", + "label": "blake2s256" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify", + "label": "ecdsa_secp256k1_verify" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify", + "label": "ecdsa_secp256r1_verify" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/keccak256", + "label": "keccak256" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/sha256", + "label": "sha256" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/xor", + "label": "xor" + } + ] + } + ] + }, + { + "type": "category", + "label": "Backend Barretenberg", + "link": { + "type": "doc", + "id": "noir_js/reference/backend_barretenberg/index" + }, + "items": [ + { + "type": "category", + "label": "Classes", + "items": [ + { + "type": "doc", + "id": "noir_js/reference/backend_barretenberg/classes/BarretenbergBackend", + "label": "BarretenbergBackend" + } + ] + }, + { + "type": "category", + "label": "Interfaces", + "items": [ + { + "type": "doc", + "id": "noir_js/reference/backend_barretenberg/interfaces/Backend", + "label": "Backend" + } + ] + }, + { + "type": "category", + "label": "Type Aliases", + "items": [ + { + "type": "doc", + "id": "noir_js/reference/backend_barretenberg/type-aliases/BackendOptions", + "label": "BackendOptions" + }, + { + "type": "doc", + "id": "noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit", + "label": "CompiledCircuit" + }, + { + "type": "doc", + "id": "noir_js/reference/backend_barretenberg/type-aliases/ProofData", + "label": "ProofData" + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "doc", + "id": "migration_notes", + "label": "Migration notes" + } + ] +} diff --git a/docs/versioned_sidebars/version-v0.19.4-sidebars.json b/docs/versioned_sidebars/version-v0.19.4-sidebars.json new file mode 100644 index 0000000000..a1675eca18 --- /dev/null +++ b/docs/versioned_sidebars/version-v0.19.4-sidebars.json @@ -0,0 +1,293 @@ +{ + "sidebar": [ + { + "type": "doc", + "id": "index", + "label": "Noir" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "autogenerated", + "dirName": "getting_started" + } + ] + }, + { + "type": "category", + "label": "Examples", + "items": [ + { + "type": "autogenerated", + "dirName": "examples" + } + ] + }, + { + "type": "category", + "label": "Nargo", + "items": [ + { + "type": "autogenerated", + "dirName": "nargo" + } + ] + }, + { + "type": "category", + "label": "Language Concepts", + "items": [ + { + "type": "category", + "label": "Data Types", + "link": { + "type": "doc", + "id": "language_concepts/data_types" + }, + "items": [ + { + "type": "autogenerated", + "dirName": "language_concepts/data_types" + } + ] + }, + "language_concepts/functions", + "language_concepts/control_flow", + "language_concepts/ops", + "language_concepts/assert", + "language_concepts/unconstrained", + "language_concepts/generics", + "language_concepts/mutability", + "language_concepts/lambdas", + "language_concepts/comments", + "language_concepts/distinct", + "language_concepts/shadowing" + ] + }, + { + "type": "category", + "label": "Noir Standard Library", + "items": [ + { + "type": "category", + "label": "Cryptographic Primitives", + "link": { + "type": "doc", + "id": "standard_library/cryptographic_primitives" + }, + "items": [ + { + "type": "autogenerated", + "dirName": "standard_library/cryptographic_primitives" + } + ] + }, + "standard_library/recursion", + "standard_library/logging", + "standard_library/merkle_trees", + "standard_library/zeroed", + "standard_library/black_box_fns", + "standard_library/options" + ] + }, + { + "type": "category", + "label": "Modules, Packages and Crates", + "items": [ + { + "type": "autogenerated", + "dirName": "modules_packages_crates" + } + ] + }, + { + "type": "category", + "label": "NoirJS", + "link": { + "type": "doc", + "id": "noir_js/noir_js" + }, + "items": [ + { + "type": "category", + "label": "Guides", + "items": [ + { + "type": "autogenerated", + "dirName": "noir_js/getting_started" + } + ] + }, + { + "type": "category", + "label": "Reference", + "items": [ + { + "type": "category", + "label": "Noir JS", + "link": { + "type": "doc", + "id": "noir_js/reference/noir_js/index" + }, + "items": [ + { + "type": "category", + "label": "Classes", + "items": [ + { + "type": "doc", + "id": "noir_js/reference/noir_js/classes/Noir", + "label": "Noir" + } + ] + }, + { + "type": "category", + "label": "Type Aliases", + "items": [ + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/CompiledCircuit", + "label": "CompiledCircuit" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/ForeignCallHandler", + "label": "ForeignCallHandler" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/ForeignCallInput", + "label": "ForeignCallInput" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/ForeignCallOutput", + "label": "ForeignCallOutput" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/InputMap", + "label": "InputMap" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/ProofData", + "label": "ProofData" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/type-aliases/WitnessMap", + "label": "WitnessMap" + } + ] + }, + { + "type": "category", + "label": "Functions", + "items": [ + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/and", + "label": "and" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/blake2s256", + "label": "blake2s256" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify", + "label": "ecdsa_secp256k1_verify" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify", + "label": "ecdsa_secp256r1_verify" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/keccak256", + "label": "keccak256" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/sha256", + "label": "sha256" + }, + { + "type": "doc", + "id": "noir_js/reference/noir_js/functions/xor", + "label": "xor" + } + ] + } + ] + }, + { + "type": "category", + "label": "Backend Barretenberg", + "link": { + "type": "doc", + "id": "noir_js/reference/backend_barretenberg/index" + }, + "items": [ + { + "type": "category", + "label": "Classes", + "items": [ + { + "type": "doc", + "id": "noir_js/reference/backend_barretenberg/classes/BarretenbergBackend", + "label": "BarretenbergBackend" + } + ] + }, + { + "type": "category", + "label": "Interfaces", + "items": [ + { + "type": "doc", + "id": "noir_js/reference/backend_barretenberg/interfaces/Backend", + "label": "Backend" + } + ] + }, + { + "type": "category", + "label": "Type Aliases", + "items": [ + { + "type": "doc", + "id": "noir_js/reference/backend_barretenberg/type-aliases/BackendOptions", + "label": "BackendOptions" + }, + { + "type": "doc", + "id": "noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit", + "label": "CompiledCircuit" + }, + { + "type": "doc", + "id": "noir_js/reference/backend_barretenberg/type-aliases/ProofData", + "label": "ProofData" + } + ] + } + ] + } + ] + } + ] + }, + { + "type": "doc", + "id": "migration_notes", + "label": "Migration notes" + } + ] +} diff --git a/docs/versioned_sidebars/version-v0.6.0-sidebars.json b/docs/versioned_sidebars/version-v0.6.0-sidebars.json deleted file mode 100644 index 7323ae1c50..0000000000 --- a/docs/versioned_sidebars/version-v0.6.0-sidebars.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts" - } - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/array_methods", - "standard_library/field_methods", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "doc", - "id": "typescript", - "label": "Working with Typescript" - } - ] -} diff --git a/docs/versioned_sidebars/version-v0.7.1-sidebars.json b/docs/versioned_sidebars/version-v0.7.1-sidebars.json deleted file mode 100644 index 7323ae1c50..0000000000 --- a/docs/versioned_sidebars/version-v0.7.1-sidebars.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts" - } - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/array_methods", - "standard_library/field_methods", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "doc", - "id": "typescript", - "label": "Working with Typescript" - } - ] -} diff --git a/docs/versioned_sidebars/version-v0.9.0-sidebars.json b/docs/versioned_sidebars/version-v0.9.0-sidebars.json deleted file mode 100644 index 190363917e..0000000000 --- a/docs/versioned_sidebars/version-v0.9.0-sidebars.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "sidebar": [ - { - "type": "doc", - "id": "index", - "label": "Noir" - }, - { - "type": "category", - "label": "Getting Started", - "items": [ - { - "type": "autogenerated", - "dirName": "getting_started" - } - ] - }, - { - "type": "category", - "label": "Examples", - "items": [ - { - "type": "autogenerated", - "dirName": "examples" - } - ] - }, - { - "type": "category", - "label": "Nargo", - "items": [ - { - "type": "autogenerated", - "dirName": "nargo" - } - ] - }, - { - "type": "category", - "label": "Language Concepts", - "items": [ - { - "type": "autogenerated", - "dirName": "language_concepts" - } - ] - }, - { - "type": "category", - "label": "Noir Standard Library", - "items": [ - { - "type": "category", - "label": "Cryptographic Primitives", - "link": { - "type": "doc", - "id": "standard_library/cryptographic_primitives" - }, - "items": [ - { - "type": "autogenerated", - "dirName": "standard_library/cryptographic_primitives" - } - ] - }, - "standard_library/slice_methods", - "standard_library/field_methods", - "standard_library/recursion", - "standard_library/logging", - "standard_library/merkle_trees", - "standard_library/zeroed", - "standard_library/black_box_fns" - ] - }, - { - "type": "category", - "label": "Modules, Packages and Crates", - "items": [ - { - "type": "autogenerated", - "dirName": "modules_packages_crates" - } - ] - }, - { - "type": "doc", - "id": "typescript", - "label": "Working with Typescript" - } - ] -} diff --git a/docs/versions.json b/docs/versions.json index ebd565cb0a..7e140c94b7 100644 --- a/docs/versions.json +++ b/docs/versions.json @@ -1,5 +1,4 @@ [ - "v0.19.2", - "v0.17.0", - "v0.10.5" + "v0.19.4", + "v0.17.0" ] diff --git a/flake.nix b/flake.nix index 0091a49f24..0ec712aa08 100644 --- a/flake.nix +++ b/flake.nix @@ -73,7 +73,7 @@ # Configuration shared between builds config = { # x-release-please-start-version - version = "0.19.2"; + version = "0.20.0"; # x-release-please-end src = pkgs.lib.cleanSourceWith { diff --git a/noir_stdlib/src/default.nr b/noir_stdlib/src/default.nr new file mode 100644 index 0000000000..232be74489 --- /dev/null +++ b/noir_stdlib/src/default.nr @@ -0,0 +1,48 @@ +trait Default { + fn default() -> Self; +} + +impl Default for Field { fn default() -> Field { 0 } } + +impl Default for u8 { fn default() -> u8 { 0 } } +impl Default for u16 { fn default() -> u16 { 0 } } +impl Default for u32 { fn default() -> u32 { 0 } } +impl Default for u64 { fn default() -> u64 { 0 } } + +impl Default for i8 { fn default() -> i8 { 0 } } +impl Default for i16 { fn default() -> i16 { 0 } } +impl Default for i32 { fn default() -> i32 { 0 } } +impl Default for i64 { fn default() -> i64 { 0 } } + +impl Default for () { fn default() -> () { () } } +impl Default for bool { fn default() -> bool { false } } + +impl Default for [T; N] where T: Default { + fn default() -> [T; N] { + [T::default(); N] + } +} + +impl Default for (A, B) where A: Default, B: Default { + fn default() -> (A, B) { + (A::default(), B::default()) + } +} + +impl Default for (A, B, C) where A: Default, B: Default, C: Default { + fn default() -> (A, B, C) { + (A::default(), B::default(), C::default()) + } +} + +impl Default for (A, B, C, D) where A: Default, B: Default, C: Default, D: Default { + fn default() -> (A, B, C, D) { + (A::default(), B::default(), C::default(), D::default()) + } +} + +impl Default for (A, B, C, D, E) where A: Default, B: Default, C: Default, D: Default, E: Default { + fn default() -> (A, B, C, D, E) { + (A::default(), B::default(), C::default(), D::default(), E::default()) + } +} diff --git a/noir_stdlib/src/ec/consts/te.nr b/noir_stdlib/src/ec/consts/te.nr index 469493a35e..e25f373593 100644 --- a/noir_stdlib/src/ec/consts/te.nr +++ b/noir_stdlib/src/ec/consts/te.nr @@ -12,14 +12,20 @@ struct BabyJubjub { pub fn baby_jubjub() -> BabyJubjub { BabyJubjub { // Baby Jubjub (ERC-2494) parameters in affine representation - curve: TECurve::new(168700, + curve: TECurve::new( + 168700, 168696, // G - TEPoint::new(995203441582195749578291179787384436505546430278305826713579947235728471134, - 5472060717959818805561601436314318772137091100104008585924551046643952123905)), + TEPoint::new( + 995203441582195749578291179787384436505546430278305826713579947235728471134, + 5472060717959818805561601436314318772137091100104008585924551046643952123905 + ) + ), // [8]G precalculated - base8: TEPoint::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, - 16950150798460657717958625567821834550301663161624707787222815936182638968203), + base8: TEPoint::new( + 5299619240641551281634865583518297030282874472190772894086521144482721001553, + 16950150798460657717958625567821834550301663161624707787222815936182638968203 + ), // The size of the group formed from multiplying the base field by 8. suborder: 2736030358979909402780800718157159386076813972158567259200215660948447373041 } diff --git a/noir_stdlib/src/ecdsa_secp256k1.nr b/noir_stdlib/src/ecdsa_secp256k1.nr index 61687f557f..b1f2b12c76 100644 --- a/noir_stdlib/src/ecdsa_secp256k1.nr +++ b/noir_stdlib/src/ecdsa_secp256k1.nr @@ -1,2 +1,7 @@ #[foreign(ecdsa_secp256k1)] -pub fn verify_signature(_public_key_x: [u8; 32], _public_key_y: [u8; 32], _signature: [u8; 64], _message_hash: [u8; N]) -> bool {} +pub fn verify_signature( + _public_key_x: [u8; 32], + _public_key_y: [u8; 32], + _signature: [u8; 64], + _message_hash: [u8; N] +) -> bool {} diff --git a/noir_stdlib/src/ecdsa_secp256r1.nr b/noir_stdlib/src/ecdsa_secp256r1.nr index 7af37407ed..6c3cf4d794 100644 --- a/noir_stdlib/src/ecdsa_secp256r1.nr +++ b/noir_stdlib/src/ecdsa_secp256r1.nr @@ -1,2 +1,7 @@ #[foreign(ecdsa_secp256r1)] -pub fn verify_signature(_public_key_x: [u8; 32], _public_key_y: [u8; 32], _signature: [u8; 64], _message_hash: [u8; N]) -> bool {} +pub fn verify_signature( + _public_key_x: [u8; 32], + _public_key_y: [u8; 32], + _signature: [u8; 64], + _message_hash: [u8; N] +) -> bool {} diff --git a/noir_stdlib/src/hash/poseidon.nr b/noir_stdlib/src/hash/poseidon.nr index b3cb32cd35..3f4de73c0d 100644 --- a/noir_stdlib/src/hash/poseidon.nr +++ b/noir_stdlib/src/hash/poseidon.nr @@ -10,7 +10,14 @@ struct PoseidonConfig { mds: [Field; N] // MDS Matrix in row-major order } -pub fn config(t: Field, rf: u8, rp: u8, alpha: Field, ark: [Field; M], mds: [Field; N]) -> PoseidonConfig { +pub fn config( + t: Field, + rf: u8, + rp: u8, + alpha: Field, + ark: [Field; M], + mds: [Field; N] +) -> PoseidonConfig { // Input checks let mul = crate::wrapping_mul(t as u8, (rf + rp)); assert(mul == ark.len() as u8); diff --git a/noir_stdlib/src/lib.nr b/noir_stdlib/src/lib.nr index 916e71cb49..70b4681b54 100644 --- a/noir_stdlib/src/lib.nr +++ b/noir_stdlib/src/lib.nr @@ -19,13 +19,21 @@ mod compat; mod option; mod string; mod test; +mod ops; +mod default; +mod prelude; + // Oracle calls are required to be wrapped in an unconstrained function -// Thus, the only argument to the `println` oracle is expected to always be an ident -#[oracle(println)] -unconstrained fn println_oracle(_input: T) {} +// Thus, the only argument to the `println` oracle is expected to always be an ident +#[oracle(print)] +unconstrained fn print_oracle(_with_newline: bool, _input: T) {} + +unconstrained pub fn print(input: T) { + print_oracle(false, input); +} unconstrained pub fn println(input: T) { - println_oracle(input); + print_oracle(true, input); } #[foreign(recursive_aggregation)] @@ -61,7 +69,3 @@ pub fn wrapping_sub(x: T, y: T) -> T { pub fn wrapping_mul(x: T, y: T) -> T { crate::from_field(crate::as_field(x) * crate::as_field(y)) } -/// Shift-left x by y bits -/// If the result overflow the bitsize; it does not fail and returns 0 instead -#[builtin(wrapping_shift_left)] -pub fn wrapping_shift_left(_x: T, _y: T) -> T {} diff --git a/noir_stdlib/src/ops.nr b/noir_stdlib/src/ops.nr new file mode 100644 index 0000000000..23acc2f0e5 --- /dev/null +++ b/noir_stdlib/src/ops.nr @@ -0,0 +1,117 @@ + +trait Add { + fn add(self, other: Self) -> Self; +} + +impl Add for Field { fn add(self, other: Field) -> Field { self + other } } + +impl Add for u8 { fn add(self, other: u8) -> u8 { self + other } } +impl Add for u16 { fn add(self, other: u16) -> u16 { self + other } } +impl Add for u32 { fn add(self, other: u32) -> u32 { self + other } } +impl Add for u64 { fn add(self, other: u64) -> u64 { self + other } } + +impl Add for i8 { fn add(self, other: i8) -> i8 { self + other } } +impl Add for i16 { fn add(self, other: i16) -> i16 { self + other } } +impl Add for i32 { fn add(self, other: i32) -> i32 { self + other } } +impl Add for i64 { fn add(self, other: i64) -> i64 { self + other } } + +trait Sub { + fn sub(self, other: Self) -> Self; +} + +impl Sub for Field { fn sub(self, other: Field) -> Field { self - other } } + +impl Sub for u8 { fn sub(self, other: u8) -> u8 { self - other } } +impl Sub for u16 { fn sub(self, other: u16) -> u16 { self - other } } +impl Sub for u32 { fn sub(self, other: u32) -> u32 { self - other } } +impl Sub for u64 { fn sub(self, other: u64) -> u64 { self - other } } + +impl Sub for i8 { fn sub(self, other: i8) -> i8 { self - other } } +impl Sub for i16 { fn sub(self, other: i16) -> i16 { self - other } } +impl Sub for i32 { fn sub(self, other: i32) -> i32 { self - other } } +impl Sub for i64 { fn sub(self, other: i64) -> i64 { self - other } } + +trait Mul { + fn mul(self, other: Self) -> Self; +} + +impl Mul for Field { fn mul(self, other: Field) -> Field { self * other } } + +impl Mul for u8 { fn mul(self, other: u8) -> u8 { self * other } } +impl Mul for u16 { fn mul(self, other: u16) -> u16 { self * other } } +impl Mul for u32 { fn mul(self, other: u32) -> u32 { self * other } } +impl Mul for u64 { fn mul(self, other: u64) -> u64 { self * other } } + +impl Mul for i8 { fn mul(self, other: i8) -> i8 { self * other } } +impl Mul for i16 { fn mul(self, other: i16) -> i16 { self * other } } +impl Mul for i32 { fn mul(self, other: i32) -> i32 { self * other } } +impl Mul for i64 { fn mul(self, other: i64) -> i64 { self * other } } + +trait Div { + fn div(self, other: Self) -> Self; +} + +impl Div for Field { fn div(self, other: Field) -> Field { self / other } } + +impl Div for u8 { fn div(self, other: u8) -> u8 { self / other } } +impl Div for u16 { fn div(self, other: u16) -> u16 { self / other } } +impl Div for u32 { fn div(self, other: u32) -> u32 { self / other } } +impl Div for u64 { fn div(self, other: u64) -> u64 { self / other } } + +impl Div for i8 { fn div(self, other: i8) -> i8 { self / other } } +impl Div for i16 { fn div(self, other: i16) -> i16 { self / other } } +impl Div for i32 { fn div(self, other: i32) -> i32 { self / other } } +impl Div for i64 { fn div(self, other: i64) -> i64 { self / other } } + +trait Eq { + fn eq(self, other: Self) -> bool; +} + +impl Eq for Field { fn eq(self, other: Field) -> bool { self == other } } + +impl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } } +impl Eq for u16 { fn eq(self, other: u16) -> bool { self == other } } +impl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } } +impl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } } + +impl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } } +impl Eq for i16 { fn eq(self, other: i16) -> bool { self == other } } +impl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } } +impl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } } + +impl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } } +impl Eq for bool { fn eq(self, other: bool) -> bool { self == other } } + +impl Eq for [T; N] where T: Eq { + fn eq(self, other: [T; N]) -> bool { + let mut result = true; + for i in 0 .. self.len() { + result &= self[i].eq(other[i]); + } + result + } +} + +impl Eq for (A, B) where A: Eq, B: Eq { + fn eq(self, other: (A, B)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) + } +} + +impl Eq for (A, B, C) where A: Eq, B: Eq, C: Eq { + fn eq(self, other: (A, B, C)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) + } +} + +impl Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq { + fn eq(self, other: (A, B, C, D)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) + } +} + +impl Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { + fn eq(self, other: (A, B, C, D, E)) -> bool { + self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) & self.4.eq(other.4) + } +} diff --git a/noir_stdlib/src/prelude.nr b/noir_stdlib/src/prelude.nr new file mode 100644 index 0000000000..f33a1f7e7f --- /dev/null +++ b/noir_stdlib/src/prelude.nr @@ -0,0 +1,3 @@ +use crate::collections::vec::Vec; +use crate::option::Option; +use crate::{print, println, assert_constant}; diff --git a/noir_stdlib/src/schnorr.nr b/noir_stdlib/src/schnorr.nr index c78eae3724..5ed95096f9 100644 --- a/noir_stdlib/src/schnorr.nr +++ b/noir_stdlib/src/schnorr.nr @@ -1,2 +1,7 @@ #[foreign(schnorr_verify)] -pub fn verify_signature(_public_key_x: Field, _public_key_y: Field, _signature: [u8; 64], _message: [u8; N]) -> bool {} +pub fn verify_signature( + _public_key_x: Field, + _public_key_y: Field, + _signature: [u8; 64], + _message: [u8; N] +) -> bool {} diff --git a/noir_stdlib/src/sha256.nr b/noir_stdlib/src/sha256.nr index 4adb93f384..39e39b8cb6 100644 --- a/noir_stdlib/src/sha256.nr +++ b/noir_stdlib/src/sha256.nr @@ -6,7 +6,7 @@ fn rotr32(a: u32, b: u32) -> u32 // 32-bit right rotation { // None of the bits overlap between `(a >> b)` and `(a << (32 - b))` // Addition is then equivalent to OR, with fewer constraints. - (a >> b) + (crate::wrapping_shift_left(a, 32 - b)) + (a >> b) + (a << (32 - b)) } fn ch(x: u32, y: u32, z: u32) -> u32 { @@ -66,9 +66,13 @@ fn sha_c(msg: [u32; 16], hash: [u32; 8]) -> [u32; 8] { let mut out_h: [u32; 8] = hash; let w = sha_w(msg); for j in 0..64 { - let t1 = crate::wrapping_add(crate::wrapping_add(crate::wrapping_add(out_h[7], bigma1(out_h[4])), - ch(out_h[4], out_h[5], out_h[6])), - crate::wrapping_add(K[j], w[j])); + let t1 = crate::wrapping_add( + crate::wrapping_add( + crate::wrapping_add(out_h[7], bigma1(out_h[4])), + ch(out_h[4], out_h[5], out_h[6]) + ), + crate::wrapping_add(K[j], w[j]) + ); let t2 = crate::wrapping_add(bigma0(out_h[0]), maj(out_h[0], out_h[1], out_h[2])); out_h[7] = out_h[6]; out_h[6] = out_h[5]; diff --git a/noir_stdlib/src/sha512.nr b/noir_stdlib/src/sha512.nr index ad2926aea8..155ba593bb 100644 --- a/noir_stdlib/src/sha512.nr +++ b/noir_stdlib/src/sha512.nr @@ -6,7 +6,7 @@ fn rotr64(a: u64, b: u64) -> u64 // 64-bit right rotation { // None of the bits overlap between `(a >> b)` and `(a << (64 - b))` // Addition is then equivalent to OR, with fewer constraints. - (a >> b) + (crate::wrapping_shift_left(a, 64 - b)) + (a >> b) + (a << (64 - b)) } fn sha_ch(x: u64, y: u64, z: u64) -> u64 { diff --git a/noir_stdlib/src/slice.nr b/noir_stdlib/src/slice.nr index ca06e2aae4..a5a9a38ed5 100644 --- a/noir_stdlib/src/slice.nr +++ b/noir_stdlib/src/slice.nr @@ -21,28 +21,16 @@ impl [T] { #[builtin(slice_pop_front)] pub fn pop_front(_self: Self) -> (T, Self) { } - pub fn insert(self, _index: Field, _elem: T) -> Self { - // TODO(#2462): Slice insert with a dynamic index - crate::assert_constant(_index); - self.__slice_insert(_index, _elem) - } - /// Insert an element at a specified index, shifting all elements /// after it to the right #[builtin(slice_insert)] - fn __slice_insert(_self: Self, _index: Field, _elem: T) -> Self { } - - pub fn remove(self, _index: Field) -> (Self, T) { - // TODO(#2462): Slice remove with a dynamic index - crate::assert_constant(_index); - self.__slice_remove(_index) - } + pub fn insert(_self: Self, _index: Field, _elem: T) -> Self { } /// Remove an element at a specified index, shifting all elements /// after it to the left, returning the altered slice and /// the removed element #[builtin(slice_remove)] - fn __slice_remove(_self: Self, _index: Field) -> (Self, T) { } + pub fn remove(_self: Self, _index: Field) -> (Self, T) { } // Append each element of the `other` slice to the end of `self`. // This returns a new slice and leaves both input slices unchanged. diff --git a/package.json b/package.json index 0e86b100b7..20a5b87cfd 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,6 @@ "private": true, "workspaces": [ "compiler/wasm", - "compiler/source-resolver", "compiler/integration-tests", "tooling/noir_js_types", "tooling/noirc_abi_wasm", @@ -19,7 +18,7 @@ "test": "yarn workspaces foreach run test", "test:integration": "yarn workspace integration-tests test", "clean:workspaces": "yarn workspaces foreach --exclude @noir-lang/root run clean", - "clean:root": "rm -rf ./result ./target", + "clean:root": "rm -rf ./result ./target ./packages", "clean": "yarn clean:workspaces && yarn clean:root", "lint": "yarn workspaces foreach --verbose run lint", "install:acvm_js": "yarn workspace @noir-lang/acvm_js run install:from:nix", @@ -27,10 +26,9 @@ "install:noirc_abi_wasm": "yarn workspace @noir-lang/noirc_abi run install:from:nix", "install:from:nix": "yarn install:acvm_js && yarn install:noir_wasm && yarn install:noirc_abi_wasm", "build:types": "yarn workspace @noir-lang/types run build", - "build:source-resolver": "yarn workspace @noir-lang/source-resolver run build", "build:backend_barretenberg": "yarn workspace @noir-lang/backend_barretenberg run build", "build:noir_js": "yarn workspace @noir-lang/noir_js run build", - "build:js:only": "yarn build:types && yarn build:source-resolver && yarn build:backend_barretenberg && yarn build:noir_js", + "build:js:only": "yarn build:types && yarn build:backend_barretenberg && yarn build:noir_js", "prepare:publish": "yarn clean && yarn install:from:nix && yarn build:js:only", "nightly:version": "yarn workspaces foreach run nightly:version", "publish:all": "yarn install && yarn workspaces foreach run publish" diff --git a/release-please-config.json b/release-please-config.json index afc0bfd420..562de471f0 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -14,11 +14,6 @@ "extra-files": [ "Cargo.toml", "flake.nix", - { - "type": "json", - "path": "compiler/source-resolver/package.json", - "jsonpath": "$.version" - }, { "type": "json", "path": "compiler/wasm/package.json", @@ -48,6 +43,11 @@ "type": "json", "path": "tooling/noirc_abi_wasm/package.json", "jsonpath": "$.version" + }, + { + "type": "json", + "path": "docs/docs/package.json", + "jsonpath": "$.version" } ] }, @@ -66,7 +66,11 @@ "brillig/Cargo.toml", "brillig_vm/Cargo.toml", "stdlib/Cargo.toml", - "flake.nix", + { + "type": "json", + "path": "acvm_js/package.json", + "jsonpath": "$.version" + }, { "type": "json", "path": "acvm_js/package.json", diff --git a/release-tests/test/6_array.test.js b/release-tests/test/6_array.test.js index 530b7f85bf..43d4a38926 100644 --- a/release-tests/test/6_array.test.js +++ b/release-tests/test/6_array.test.js @@ -19,27 +19,27 @@ test("promise resolved", async () => { promiseResolved = true; }); -test("nargo builds ../tooling/nargo_cli/tests/execution_success/6_array sucessfully", async () => { +test("nargo builds ../test_programs/execution_success/6_array sucessfully", async () => { await within(async () => { - cd("../tooling/nargo_cli/tests/execution_success/6_array"); + cd("../test_programs/execution_success/6_array"); const command = `${NARGO_BIN} check`; await $`${command}`.nothrow(); }); }); -test("nargo creates proof ../tooling/nargo_cli/tests/execution_success/6_array sucessfully", async () => { +test("nargo creates proof ../test_programs/execution_success/6_array sucessfully", async () => { await within(async () => { - cd("../tooling/nargo_cli/tests/execution_success/6_array"); + cd("../test_programs/execution_success/6_array"); const command = `${NARGO_BIN} prove 6_array`; await $`${command}`.nothrow(); }); }); -test("nargo verifies proof ../tooling/nargo_cli/tests/execution_success/6_array sucessfully", async () => { +test("nargo verifies proof ../test_programs/execution_success/6_array sucessfully", async () => { await within(async () => { - cd("../tooling/nargo_cli/tests/execution_success/6_array"); + cd("../test_programs/execution_success/6_array"); const command = `${NARGO_BIN} verify 6_array`; await $`${command}`.nothrow(); diff --git a/scripts/bootstrap_native.sh b/scripts/bootstrap_native.sh new file mode 100755 index 0000000000..481c76a263 --- /dev/null +++ b/scripts/bootstrap_native.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -eu + +cd $(dirname "$0")/.. + +# If this project has been subrepod into another project, set build data manually. +export SOURCE_DATE_EPOCH=$(date +%s) +export GIT_DIRTY=false +if [ -f ".gitrepo" ]; then + export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) +else + export GIT_COMMIT=$(git rev-parse --verify HEAD) +fi + +# Build native. +cargo build --release diff --git a/scripts/bootstrap_packages.sh b/scripts/bootstrap_packages.sh new file mode 100755 index 0000000000..2f293d93fa --- /dev/null +++ b/scripts/bootstrap_packages.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -eu + +cd $(dirname "$0")/.. + +./scripts/install_wasm-bindgen.sh + +# If this project has been subrepod into another project, set build data manually. +export SOURCE_DATE_EPOCH=$(date +%s) +export GIT_DIRTY=false +if [ -f ".gitrepo" ]; then + export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) +else + export GIT_COMMIT=$(git rev-parse --verify HEAD) +fi + +yarn +yarn build + +# We create a folder called packages, that contains each package as it would be published to npm, named correctly. +# These can be useful for testing, or portaling into other projects. +yarn workspaces foreach pack + +rm -rf packages && mkdir -p packages +tar zxfv acvm-repo/acvm_js/package.tgz -C packages && mv packages/package packages/acvm_js +tar zxfv compiler/wasm/package.tgz -C packages && mv packages/package packages/noir_wasm +tar zxfv tooling/noir_codegen/package.tgz -C packages && mv packages/package packages/noir_codegen +tar zxfv tooling/noir_js/package.tgz -C packages && mv packages/package packages/noir_js +tar zxfv tooling/noir_js_backend_barretenberg/package.tgz -C packages && mv packages/package packages/backend_barretenberg +tar zxfv tooling/noir_js_types/package.tgz -C packages && mv packages/package packages/types +tar zxfv tooling/noirc_abi_wasm/package.tgz -C packages && mv packages/package packages/noirc_abi diff --git a/scripts/install_wasm-bindgen.sh b/scripts/install_wasm-bindgen.sh new file mode 100755 index 0000000000..5e9f912750 --- /dev/null +++ b/scripts/install_wasm-bindgen.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -eu + +cd $(dirname "$0")/.. + +# Install wasm-bindgen-cli. +if [ "$(wasm-bindgen --version | cut -d' ' -f2)" != "0.2.86" ]; then + echo "Building wasm-bindgen..." + RUSTFLAGS="-Ctarget-feature=-crt-static" cargo install -f wasm-bindgen-cli --version 0.2.86 +fi diff --git a/scripts/nargo_compile_noir_codegen_assert_lt.sh b/scripts/nargo_compile_noir_codegen_assert_lt.sh new file mode 100755 index 0000000000..858a16cf51 --- /dev/null +++ b/scripts/nargo_compile_noir_codegen_assert_lt.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +cd ./tooling/noir_codegen/test/assert_lt +nargo compile \ No newline at end of file diff --git a/scripts/nargo_compile_noir_js_assert_lt.sh b/scripts/nargo_compile_noir_js_assert_lt.sh new file mode 100755 index 0000000000..636ae59b99 --- /dev/null +++ b/scripts/nargo_compile_noir_js_assert_lt.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +cd ./tooling/noir_js/test/noir_compiled_examples/assert_lt +nargo compile \ No newline at end of file diff --git a/scripts/nargo_compile_wasm_fixtures.sh b/scripts/nargo_compile_wasm_fixtures.sh new file mode 100755 index 0000000000..c047888e40 --- /dev/null +++ b/scripts/nargo_compile_wasm_fixtures.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +cd ./compiler/wasm/fixtures +for dir in $(ls -d */); do + pushd $dir/noir-script + nargo compile + popd +done diff --git a/scripts/test_js_packages.sh b/scripts/test_js_packages.sh new file mode 100755 index 0000000000..a5ec5b92a7 --- /dev/null +++ b/scripts/test_js_packages.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -eu + +cd $(dirname "$0")/.. + +./scripts/install_wasm-bindgen.sh + +# If this project has been subrepod into another project, set build data manually. +export SOURCE_DATE_EPOCH=$(date +%s) +export GIT_DIRTY=false +if [ -f ".gitrepo" ]; then + export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) +else + export GIT_COMMIT=$(git rev-parse --verify HEAD) +fi + +cargo build --release +export PATH="${PATH}:/usr/src/noir/target/release/" + +yarn +yarn build +npx playwright install +npx playwright install-deps + +./scripts/test.sh +yarn test \ No newline at end of file diff --git a/scripts/test_native.sh b/scripts/test_native.sh new file mode 100755 index 0000000000..bc1c47ecf1 --- /dev/null +++ b/scripts/test_native.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -eu + +cd $(dirname "$0")/.. + +# If this project has been subrepod into another project, set build data manually. +export SOURCE_DATE_EPOCH=$(date +%s) +export GIT_DIRTY=false +if [ -f ".gitrepo" ]; then + export GIT_COMMIT=$(awk '/commit =/ {print $3}' .gitrepo) +else + export GIT_COMMIT=$(git rev-parse --verify HEAD) +fi + +cargo test --workspace --locked --release \ No newline at end of file diff --git a/scripts/update-acvm-workspace-versions.sh b/scripts/update-acvm-workspace-versions.sh new file mode 100755 index 0000000000..3478333f05 --- /dev/null +++ b/scripts/update-acvm-workspace-versions.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Path to the top-level Cargo.toml +TOP_LEVEL_CARGO_TOML="Cargo.toml" + +# Temporary file to store paths +TEMP_PATHS_FILE="temp_paths.txt" + +# Extract local dependencies paths that start with "acvm-repo" +grep 'path = "acvm-repo' "$TOP_LEVEL_CARGO_TOML" | sed -E 's/.*path = "([^"]+)".*/\1/' > "$TEMP_PATHS_FILE" + +# Read each path and update the version in the top level workspace Cargo.toml file +# to match the version in the component's Cargo.toml +while IFS= read -r component_path; do + # Extract the component name + # This is acir_field for example or stdlib + component_name=$(basename "$component_path") + + # Extract the version from the component's Cargo.toml + # This is acvm-repo/acir_field for example + component_version=$(grep '^version =' "$component_path/Cargo.toml" | sed -E 's/version = "([^"]+)"/\1/') + + if [ -z "$component_version" ]; then + echo "Error: Unable to extract version for $component_name from $component_path/Cargo.toml" + continue + fi + + # Update the version in the top-level Cargo.toml + sed -i.bak -E "s|($component_name[[:space:]]*=[[:space:]]*\{[[:space:]]*version[[:space:]]*=[[:space:]]*\")([^\"]+)(\".*)|\1$component_version\3|" "$TOP_LEVEL_CARGO_TOML" + + if [ $? -ne 0 ]; then + echo "Error: Unable to update version for $component_name in $TOP_LEVEL_CARGO_TOML" + else + echo "Version for $component_name updated successfully to $component_version in $TOP_LEVEL_CARGO_TOML" + fi +done < "$TEMP_PATHS_FILE" + +# Remove temporary file and backup file +rm "$TEMP_PATHS_FILE" +rm "${TOP_LEVEL_CARGO_TOML}.bak" diff --git a/test_programs/.gitignore b/test_programs/.gitignore new file mode 100644 index 0000000000..01a3426160 --- /dev/null +++ b/test_programs/.gitignore @@ -0,0 +1 @@ +acir_artifacts diff --git a/tooling/nargo_cli/tests/README.md b/test_programs/README.md similarity index 100% rename from tooling/nargo_cli/tests/README.md rename to test_programs/README.md diff --git a/tooling/nargo_cli/tests/compile_failure/assert_constant_fail/Nargo.toml b/test_programs/compile_failure/assert_constant_fail/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/assert_constant_fail/Nargo.toml rename to test_programs/compile_failure/assert_constant_fail/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/assert_constant_fail/src/main.nr b/test_programs/compile_failure/assert_constant_fail/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/assert_constant_fail/src/main.nr rename to test_programs/compile_failure/assert_constant_fail/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/assert_eq_struct/Nargo.toml b/test_programs/compile_failure/assert_eq_struct/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/assert_eq_struct/Nargo.toml rename to test_programs/compile_failure/assert_eq_struct/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/assert_eq_struct/src/main.nr b/test_programs/compile_failure/assert_eq_struct/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/assert_eq_struct/src/main.nr rename to test_programs/compile_failure/assert_eq_struct/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/Nargo.toml b/test_programs/compile_failure/brillig_assert_fail/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/Nargo.toml rename to test_programs/compile_failure/brillig_assert_fail/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/Prover.toml b/test_programs/compile_failure/brillig_assert_fail/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/Prover.toml rename to test_programs/compile_failure/brillig_assert_fail/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/src/main.nr b/test_programs/compile_failure/brillig_assert_fail/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/src/main.nr rename to test_programs/compile_failure/brillig_assert_fail/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/constrain_typo/Nargo.toml b/test_programs/compile_failure/constrain_typo/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/constrain_typo/Nargo.toml rename to test_programs/compile_failure/constrain_typo/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/constrain_typo/src/main.nr b/test_programs/compile_failure/constrain_typo/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/constrain_typo/src/main.nr rename to test_programs/compile_failure/constrain_typo/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/custom_entry_not_found/Nargo.toml b/test_programs/compile_failure/custom_entry_not_found/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/custom_entry_not_found/Nargo.toml rename to test_programs/compile_failure/custom_entry_not_found/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/custom_entry_not_found/Prover.toml b/test_programs/compile_failure/custom_entry_not_found/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/custom_entry_not_found/Prover.toml rename to test_programs/compile_failure/custom_entry_not_found/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/custom_entry_not_found/src/main.nr b/test_programs/compile_failure/custom_entry_not_found/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/custom_entry_not_found/src/main.nr rename to test_programs/compile_failure/custom_entry_not_found/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/Nargo.toml b/test_programs/compile_failure/dep_impl_primitive/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/Nargo.toml rename to test_programs/compile_failure/dep_impl_primitive/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/Prover.toml b/test_programs/compile_failure/dep_impl_primitive/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/Prover.toml rename to test_programs/compile_failure/dep_impl_primitive/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/src/main.nr b/test_programs/compile_failure/dep_impl_primitive/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/src/main.nr rename to test_programs/compile_failure/dep_impl_primitive/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/depend_on_bin/Nargo.toml b/test_programs/compile_failure/depend_on_bin/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/depend_on_bin/Nargo.toml rename to test_programs/compile_failure/depend_on_bin/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/depend_on_bin/Prover.toml b/test_programs/compile_failure/depend_on_bin/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/depend_on_bin/Prover.toml rename to test_programs/compile_failure/depend_on_bin/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/depend_on_bin/src/main.nr b/test_programs/compile_failure/depend_on_bin/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/depend_on_bin/src/main.nr rename to test_programs/compile_failure/depend_on_bin/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/Nargo.toml b/test_programs/compile_failure/div_by_zero_constants/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/Nargo.toml rename to test_programs/compile_failure/div_by_zero_constants/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/Prover.toml b/test_programs/compile_failure/div_by_zero_constants/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/Prover.toml rename to test_programs/compile_failure/div_by_zero_constants/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/src/main.nr b/test_programs/compile_failure/div_by_zero_constants/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/src/main.nr rename to test_programs/compile_failure/div_by_zero_constants/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/Nargo.toml b/test_programs/compile_failure/div_by_zero_modulo/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/Nargo.toml rename to test_programs/compile_failure/div_by_zero_modulo/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/Prover.toml b/test_programs/compile_failure/div_by_zero_modulo/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/Prover.toml rename to test_programs/compile_failure/div_by_zero_modulo/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/src/main.nr b/test_programs/compile_failure/div_by_zero_modulo/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/src/main.nr rename to test_programs/compile_failure/div_by_zero_modulo/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_numerator_witness/Nargo.toml b/test_programs/compile_failure/div_by_zero_numerator_witness/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/div_by_zero_numerator_witness/Nargo.toml rename to test_programs/compile_failure/div_by_zero_numerator_witness/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_numerator_witness/Prover.toml b/test_programs/compile_failure/div_by_zero_numerator_witness/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/div_by_zero_numerator_witness/Prover.toml rename to test_programs/compile_failure/div_by_zero_numerator_witness/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_numerator_witness/src/main.nr b/test_programs/compile_failure/div_by_zero_numerator_witness/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/div_by_zero_numerator_witness/src/main.nr rename to test_programs/compile_failure/div_by_zero_numerator_witness/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/Nargo.toml b/test_programs/compile_failure/div_by_zero_witness/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/Nargo.toml rename to test_programs/compile_failure/div_by_zero_witness/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/Prover.toml b/test_programs/compile_failure/div_by_zero_witness/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/Prover.toml rename to test_programs/compile_failure/div_by_zero_witness/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/src/main.nr b/test_programs/compile_failure/div_by_zero_witness/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/src/main.nr rename to test_programs/compile_failure/div_by_zero_witness/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/Nargo.toml b/test_programs/compile_failure/dup_trait_implementation_4/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/Nargo.toml rename to test_programs/compile_failure/dup_trait_implementation_4/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/Prover.toml b/test_programs/compile_failure/dup_trait_implementation_4/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/Prover.toml rename to test_programs/compile_failure/dup_trait_implementation_4/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/main.nr b/test_programs/compile_failure/dup_trait_implementation_4/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/main.nr rename to test_programs/compile_failure/dup_trait_implementation_4/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/module1.nr b/test_programs/compile_failure/dup_trait_implementation_4/src/module1.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/module1.nr rename to test_programs/compile_failure/dup_trait_implementation_4/src/module1.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/module2.nr b/test_programs/compile_failure/dup_trait_implementation_4/src/module2.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/module2.nr rename to test_programs/compile_failure/dup_trait_implementation_4/src/module2.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/module3.nr b/test_programs/compile_failure/dup_trait_implementation_4/src/module3.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/module3.nr rename to test_programs/compile_failure/dup_trait_implementation_4/src/module3.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/Nargo.toml b/test_programs/compile_failure/dup_trait_implementation_5/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/Nargo.toml rename to test_programs/compile_failure/dup_trait_implementation_5/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/Prover.toml b/test_programs/compile_failure/dup_trait_implementation_5/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/Prover.toml rename to test_programs/compile_failure/dup_trait_implementation_5/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/main.nr b/test_programs/compile_failure/dup_trait_implementation_5/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/main.nr rename to test_programs/compile_failure/dup_trait_implementation_5/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/module1.nr b/test_programs/compile_failure/dup_trait_implementation_5/src/module1.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/module1.nr rename to test_programs/compile_failure/dup_trait_implementation_5/src/module1.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/module2.nr b/test_programs/compile_failure/dup_trait_implementation_5/src/module2.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/module2.nr rename to test_programs/compile_failure/dup_trait_implementation_5/src/module2.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/module3.nr b/test_programs/compile_failure/dup_trait_implementation_5/src/module3.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/module3.nr rename to test_programs/compile_failure/dup_trait_implementation_5/src/module3.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/module4.nr b/test_programs/compile_failure/dup_trait_implementation_5/src/module4.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/module4.nr rename to test_programs/compile_failure/dup_trait_implementation_5/src/module4.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/Nargo.toml b/test_programs/compile_failure/dup_trait_items_1/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/Nargo.toml rename to test_programs/compile_failure/dup_trait_items_1/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/Prover.toml b/test_programs/compile_failure/dup_trait_items_1/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/Prover.toml rename to test_programs/compile_failure/dup_trait_items_1/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/src/main.nr b/test_programs/compile_failure/dup_trait_items_1/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/src/main.nr rename to test_programs/compile_failure/dup_trait_items_1/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/Nargo.toml b/test_programs/compile_failure/dup_trait_items_2/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/Nargo.toml rename to test_programs/compile_failure/dup_trait_items_2/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/Prover.toml b/test_programs/compile_failure/dup_trait_items_2/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/Prover.toml rename to test_programs/compile_failure/dup_trait_items_2/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/src/main.nr b/test_programs/compile_failure/dup_trait_items_2/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/src/main.nr rename to test_programs/compile_failure/dup_trait_items_2/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/Nargo.toml b/test_programs/compile_failure/dup_trait_items_3/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/Nargo.toml rename to test_programs/compile_failure/dup_trait_items_3/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/Prover.toml b/test_programs/compile_failure/dup_trait_items_3/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/Prover.toml rename to test_programs/compile_failure/dup_trait_items_3/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/src/main.nr b/test_programs/compile_failure/dup_trait_items_3/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/src/main.nr rename to test_programs/compile_failure/dup_trait_items_3/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/Nargo.toml b/test_programs/compile_failure/dup_trait_items_4/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/Nargo.toml rename to test_programs/compile_failure/dup_trait_items_4/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/Prover.toml b/test_programs/compile_failure/dup_trait_items_4/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/Prover.toml rename to test_programs/compile_failure/dup_trait_items_4/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/src/main.nr b/test_programs/compile_failure/dup_trait_items_4/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/src/main.nr rename to test_programs/compile_failure/dup_trait_items_4/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/Nargo.toml b/test_programs/compile_failure/dup_trait_items_5/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/Nargo.toml rename to test_programs/compile_failure/dup_trait_items_5/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/Prover.toml b/test_programs/compile_failure/dup_trait_items_5/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/Prover.toml rename to test_programs/compile_failure/dup_trait_items_5/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/src/main.nr b/test_programs/compile_failure/dup_trait_items_5/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/src/main.nr rename to test_programs/compile_failure/dup_trait_items_5/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_6/Nargo.toml b/test_programs/compile_failure/dup_trait_items_6/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_6/Nargo.toml rename to test_programs/compile_failure/dup_trait_items_6/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_6/Prover.toml b/test_programs/compile_failure/dup_trait_items_6/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_6/Prover.toml rename to test_programs/compile_failure/dup_trait_items_6/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_6/src/main.nr b/test_programs/compile_failure/dup_trait_items_6/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dup_trait_items_6/src/main.nr rename to test_programs/compile_failure/dup_trait_items_6/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/duplicate_declaration/Nargo.toml b/test_programs/compile_failure/duplicate_declaration/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/duplicate_declaration/Nargo.toml rename to test_programs/compile_failure/duplicate_declaration/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/duplicate_declaration/src/main.nr b/test_programs/compile_failure/duplicate_declaration/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/duplicate_declaration/src/main.nr rename to test_programs/compile_failure/duplicate_declaration/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/Nargo.toml b/test_programs/compile_failure/dyn_index_fail_nested_array/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/Nargo.toml rename to test_programs/compile_failure/dyn_index_fail_nested_array/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/Prover.toml b/test_programs/compile_failure/dyn_index_fail_nested_array/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/Prover.toml rename to test_programs/compile_failure/dyn_index_fail_nested_array/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/src/main.nr b/test_programs/compile_failure/dyn_index_fail_nested_array/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/src/main.nr rename to test_programs/compile_failure/dyn_index_fail_nested_array/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/Nargo.toml b/test_programs/compile_failure/dynamic_index_failure/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/Nargo.toml rename to test_programs/compile_failure/dynamic_index_failure/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/Prover.toml b/test_programs/compile_failure/dynamic_index_failure/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/Prover.toml rename to test_programs/compile_failure/dynamic_index_failure/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/src/main.nr b/test_programs/compile_failure/dynamic_index_failure/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/src/main.nr rename to test_programs/compile_failure/dynamic_index_failure/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/field_modulo/Nargo.toml b/test_programs/compile_failure/field_modulo/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/field_modulo/Nargo.toml rename to test_programs/compile_failure/field_modulo/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/field_modulo/src/main.nr b/test_programs/compile_failure/field_modulo/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/field_modulo/src/main.nr rename to test_programs/compile_failure/field_modulo/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/integer_literal_overflow/Nargo.toml b/test_programs/compile_failure/integer_literal_overflow/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/integer_literal_overflow/Nargo.toml rename to test_programs/compile_failure/integer_literal_overflow/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/integer_literal_overflow/src/main.nr b/test_programs/compile_failure/integer_literal_overflow/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/integer_literal_overflow/src/main.nr rename to test_programs/compile_failure/integer_literal_overflow/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/invalid_dependency_name/Nargo.toml b/test_programs/compile_failure/invalid_dependency_name/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/invalid_dependency_name/Nargo.toml rename to test_programs/compile_failure/invalid_dependency_name/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/invalid_dependency_name/src/main.nr b/test_programs/compile_failure/invalid_dependency_name/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/invalid_dependency_name/src/main.nr rename to test_programs/compile_failure/invalid_dependency_name/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/multiple_contracts/Nargo.toml b/test_programs/compile_failure/multiple_contracts/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/multiple_contracts/Nargo.toml rename to test_programs/compile_failure/multiple_contracts/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/multiple_contracts/src/main.nr b/test_programs/compile_failure/multiple_contracts/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/multiple_contracts/src/main.nr rename to test_programs/compile_failure/multiple_contracts/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/multiple_primary_attributes_fail/Nargo.toml b/test_programs/compile_failure/multiple_primary_attributes_fail/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/multiple_primary_attributes_fail/Nargo.toml rename to test_programs/compile_failure/multiple_primary_attributes_fail/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/multiple_primary_attributes_fail/src/main.nr b/test_programs/compile_failure/multiple_primary_attributes_fail/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/multiple_primary_attributes_fail/src/main.nr rename to test_programs/compile_failure/multiple_primary_attributes_fail/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/mutability_regression_2911/Nargo.toml b/test_programs/compile_failure/mutability_regression_2911/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/mutability_regression_2911/Nargo.toml rename to test_programs/compile_failure/mutability_regression_2911/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/mutability_regression_2911/src/main.nr b/test_programs/compile_failure/mutability_regression_2911/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/mutability_regression_2911/src/main.nr rename to test_programs/compile_failure/mutability_regression_2911/src/main.nr diff --git a/test_programs/compile_failure/negate_unsigned/Nargo.toml b/test_programs/compile_failure/negate_unsigned/Nargo.toml new file mode 100644 index 0000000000..0b5486024c --- /dev/null +++ b/test_programs/compile_failure/negate_unsigned/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "negate_unsigned" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/Prover.toml b/test_programs/compile_failure/negate_unsigned/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/Prover.toml rename to test_programs/compile_failure/negate_unsigned/Prover.toml diff --git a/test_programs/compile_failure/negate_unsigned/src/main.nr b/test_programs/compile_failure/negate_unsigned/src/main.nr new file mode 100644 index 0000000000..db5f9b0820 --- /dev/null +++ b/test_programs/compile_failure/negate_unsigned/src/main.nr @@ -0,0 +1,6 @@ +use dep::std; + +fn main() { + let var = -1 as u8; + std::println(var); +} diff --git a/tooling/nargo_cli/tests/compile_failure/no_impl_from_function/Nargo.toml b/test_programs/compile_failure/no_impl_from_function/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/no_impl_from_function/Nargo.toml rename to test_programs/compile_failure/no_impl_from_function/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/no_impl_from_function/src/main.nr b/test_programs/compile_failure/no_impl_from_function/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/no_impl_from_function/src/main.nr rename to test_programs/compile_failure/no_impl_from_function/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/no_nested_impl/Nargo.toml b/test_programs/compile_failure/no_nested_impl/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/no_nested_impl/Nargo.toml rename to test_programs/compile_failure/no_nested_impl/Nargo.toml diff --git a/test_programs/compile_failure/no_nested_impl/src/main.nr b/test_programs/compile_failure/no_nested_impl/src/main.nr new file mode 100644 index 0000000000..1f1056fb6d --- /dev/null +++ b/test_programs/compile_failure/no_nested_impl/src/main.nr @@ -0,0 +1,21 @@ +fn main() { + let a: [[[[Field; 2]; 2]; 2]; 2] = [[[[1, 2], [3, 4]], [[5, 6], [7, 8]]], [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]]; + assert(a.my_eq(a)); +} + +trait MyEq { + fn my_eq(self, other: Self) -> bool; +} + +impl MyEq for [T; 2] where T: MyEq { + fn my_eq(self, other: Self) -> bool { + self[0].my_eq(other[0]) + & self[0].my_eq(other[0]) + } +} +// Impl for u32 but not Field +impl MyEq for u32 { + fn my_eq(self, other: Self) -> bool { + self == other + } +} diff --git a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/Nargo.toml b/test_programs/compile_failure/orphaned_trait_impl/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/Nargo.toml rename to test_programs/compile_failure/orphaned_trait_impl/Nargo.toml diff --git a/compiler/integration-tests/circuits/main/Prover.toml b/test_programs/compile_failure/orphaned_trait_impl/Prover.toml similarity index 100% rename from compiler/integration-tests/circuits/main/Prover.toml rename to test_programs/compile_failure/orphaned_trait_impl/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate1/Nargo.toml b/test_programs/compile_failure/orphaned_trait_impl/crate1/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate1/Nargo.toml rename to test_programs/compile_failure/orphaned_trait_impl/crate1/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate1/src/lib.nr b/test_programs/compile_failure/orphaned_trait_impl/crate1/src/lib.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate1/src/lib.nr rename to test_programs/compile_failure/orphaned_trait_impl/crate1/src/lib.nr diff --git a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate2/Nargo.toml b/test_programs/compile_failure/orphaned_trait_impl/crate2/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate2/Nargo.toml rename to test_programs/compile_failure/orphaned_trait_impl/crate2/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate2/src/lib.nr b/test_programs/compile_failure/orphaned_trait_impl/crate2/src/lib.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate2/src/lib.nr rename to test_programs/compile_failure/orphaned_trait_impl/crate2/src/lib.nr diff --git a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/src/main.nr b/test_programs/compile_failure/orphaned_trait_impl/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/src/main.nr rename to test_programs/compile_failure/orphaned_trait_impl/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/overflowing_assignment/Nargo.toml b/test_programs/compile_failure/overflowing_assignment/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/overflowing_assignment/Nargo.toml rename to test_programs/compile_failure/overflowing_assignment/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/overflowing_assignment/src/main.nr b/test_programs/compile_failure/overflowing_assignment/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/overflowing_assignment/src/main.nr rename to test_programs/compile_failure/overflowing_assignment/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/overlapping_generic_impls/Nargo.toml b/test_programs/compile_failure/overlapping_generic_impls/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/overlapping_generic_impls/Nargo.toml rename to test_programs/compile_failure/overlapping_generic_impls/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/overlapping_generic_impls/src/main.nr b/test_programs/compile_failure/overlapping_generic_impls/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/overlapping_generic_impls/src/main.nr rename to test_programs/compile_failure/overlapping_generic_impls/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/package_name_empty/Nargo.toml b/test_programs/compile_failure/package_name_empty/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/package_name_empty/Nargo.toml rename to test_programs/compile_failure/package_name_empty/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/package_name_empty/src/main.nr b/test_programs/compile_failure/package_name_empty/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/package_name_empty/src/main.nr rename to test_programs/compile_failure/package_name_empty/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/package_name_hyphen/Nargo.toml b/test_programs/compile_failure/package_name_hyphen/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/package_name_hyphen/Nargo.toml rename to test_programs/compile_failure/package_name_hyphen/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/package_name_hyphen/src/main.nr b/test_programs/compile_failure/package_name_hyphen/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/package_name_hyphen/src/main.nr rename to test_programs/compile_failure/package_name_hyphen/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml b/test_programs/compile_failure/primary_attribute_struct/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml rename to test_programs/compile_failure/primary_attribute_struct/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/src/main.nr b/test_programs/compile_failure/primary_attribute_struct/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/src/main.nr rename to test_programs/compile_failure/primary_attribute_struct/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/Nargo.toml b/test_programs/compile_failure/radix_non_constant_length/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/Nargo.toml rename to test_programs/compile_failure/radix_non_constant_length/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/Prover.toml b/test_programs/compile_failure/radix_non_constant_length/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/Prover.toml rename to test_programs/compile_failure/radix_non_constant_length/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/src/main.nr b/test_programs/compile_failure/radix_non_constant_length/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/src/main.nr rename to test_programs/compile_failure/radix_non_constant_length/src/main.nr diff --git a/test_programs/compile_failure/raw_string_huge/Nargo.toml b/test_programs/compile_failure/raw_string_huge/Nargo.toml new file mode 100644 index 0000000000..ecef0e2a07 --- /dev/null +++ b/test_programs/compile_failure/raw_string_huge/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "raw_string_huge" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_failure/raw_string_huge/src/main.nr b/test_programs/compile_failure/raw_string_huge/src/main.nr new file mode 100644 index 0000000000..7bca9942e7 --- /dev/null +++ b/test_programs/compile_failure/raw_string_huge/src/main.nr @@ -0,0 +1,4 @@ +fn main() { + // Fails because of too many hashes for raw string (256+ hashes) + let _a = r##############################################################################################################################################################################################################################################################################"hello"##############################################################################################################################################################################################################################################################################; +} diff --git a/tooling/nargo_cli/tests/compile_failure/slice_access_failure/Nargo.toml b/test_programs/compile_failure/slice_access_failure/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/slice_access_failure/Nargo.toml rename to test_programs/compile_failure/slice_access_failure/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/slice_access_failure/Prover.toml b/test_programs/compile_failure/slice_access_failure/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/slice_access_failure/Prover.toml rename to test_programs/compile_failure/slice_access_failure/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/slice_access_failure/src/main.nr b/test_programs/compile_failure/slice_access_failure/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/slice_access_failure/src/main.nr rename to test_programs/compile_failure/slice_access_failure/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/slice_insert_failure/Nargo.toml b/test_programs/compile_failure/slice_insert_failure/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/slice_insert_failure/Nargo.toml rename to test_programs/compile_failure/slice_insert_failure/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/slice_insert_failure/Prover.toml b/test_programs/compile_failure/slice_insert_failure/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/slice_insert_failure/Prover.toml rename to test_programs/compile_failure/slice_insert_failure/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/slice_insert_failure/src/main.nr b/test_programs/compile_failure/slice_insert_failure/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/slice_insert_failure/src/main.nr rename to test_programs/compile_failure/slice_insert_failure/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/slice_remove_failure/Nargo.toml b/test_programs/compile_failure/slice_remove_failure/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/slice_remove_failure/Nargo.toml rename to test_programs/compile_failure/slice_remove_failure/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/slice_remove_failure/Prover.toml b/test_programs/compile_failure/slice_remove_failure/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/slice_remove_failure/Prover.toml rename to test_programs/compile_failure/slice_remove_failure/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/slice_remove_failure/src/main.nr b/test_programs/compile_failure/slice_remove_failure/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/slice_remove_failure/src/main.nr rename to test_programs/compile_failure/slice_remove_failure/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/trait_incorrect_generic_count/Nargo.toml b/test_programs/compile_failure/trait_incorrect_generic_count/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/trait_incorrect_generic_count/Nargo.toml rename to test_programs/compile_failure/trait_incorrect_generic_count/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/trait_incorrect_generic_count/src/main.nr b/test_programs/compile_failure/trait_incorrect_generic_count/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/trait_incorrect_generic_count/src/main.nr rename to test_programs/compile_failure/trait_incorrect_generic_count/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_fail/Nargo.toml b/test_programs/compile_failure/workspace_fail/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/workspace_fail/Nargo.toml rename to test_programs/compile_failure/workspace_fail/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/Nargo.toml b/test_programs/compile_failure/workspace_fail/crates/a/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/Nargo.toml rename to test_programs/compile_failure/workspace_fail/crates/a/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/Prover.toml b/test_programs/compile_failure/workspace_fail/crates/a/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/Prover.toml rename to test_programs/compile_failure/workspace_fail/crates/a/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/src/main.nr b/test_programs/compile_failure/workspace_fail/crates/a/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/src/main.nr rename to test_programs/compile_failure/workspace_fail/crates/a/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/Nargo.toml b/test_programs/compile_failure/workspace_fail/crates/b/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/Nargo.toml rename to test_programs/compile_failure/workspace_fail/crates/b/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/Prover.toml b/test_programs/compile_failure/workspace_fail/crates/b/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/Prover.toml rename to test_programs/compile_failure/workspace_fail/crates/b/Prover.toml diff --git a/compiler/integration-tests/circuits/main/src/main.nr b/test_programs/compile_failure/workspace_fail/crates/b/src/main.nr similarity index 100% rename from compiler/integration-tests/circuits/main/src/main.nr rename to test_programs/compile_failure/workspace_fail/crates/b/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/Nargo.toml b/test_programs/compile_failure/workspace_missing_toml/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/Nargo.toml rename to test_programs/compile_failure/workspace_missing_toml/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/a/Prover.toml b/test_programs/compile_failure/workspace_missing_toml/crates/a/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/a/Prover.toml rename to test_programs/compile_failure/workspace_missing_toml/crates/a/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/workspace/crates/a/src/main.nr b/test_programs/compile_failure/workspace_missing_toml/crates/a/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace/crates/a/src/main.nr rename to test_programs/compile_failure/workspace_missing_toml/crates/a/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/b/Nargo.toml b/test_programs/compile_failure/workspace_missing_toml/crates/b/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/b/Nargo.toml rename to test_programs/compile_failure/workspace_missing_toml/crates/b/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/b/Prover.toml b/test_programs/compile_failure/workspace_missing_toml/crates/b/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/b/Prover.toml rename to test_programs/compile_failure/workspace_missing_toml/crates/b/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/src/main.nr b/test_programs/compile_failure/workspace_missing_toml/crates/b/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/src/main.nr rename to test_programs/compile_failure/workspace_missing_toml/crates/b/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_contract/contract_with_impl/Nargo.toml b/test_programs/compile_success_contract/contract_with_impl/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_contract/contract_with_impl/Nargo.toml rename to test_programs/compile_success_contract/contract_with_impl/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_contract/contract_with_impl/src/main.nr b/test_programs/compile_success_contract/contract_with_impl/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_contract/contract_with_impl/src/main.nr rename to test_programs/compile_success_contract/contract_with_impl/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_contract/non_entry_point_method/Nargo.toml b/test_programs/compile_success_contract/non_entry_point_method/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_contract/non_entry_point_method/Nargo.toml rename to test_programs/compile_success_contract/non_entry_point_method/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_contract/non_entry_point_method/src/main.nr b/test_programs/compile_success_contract/non_entry_point_method/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_contract/non_entry_point_method/src/main.nr rename to test_programs/compile_success_contract/non_entry_point_method/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_contract/simple_contract/Nargo.toml b/test_programs/compile_success_contract/simple_contract/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_contract/simple_contract/Nargo.toml rename to test_programs/compile_success_contract/simple_contract/Nargo.toml diff --git a/test_programs/compile_success_contract/simple_contract/src/main.nr b/test_programs/compile_success_contract/simple_contract/src/main.nr new file mode 100644 index 0000000000..fea0ae08c2 --- /dev/null +++ b/test_programs/compile_success_contract/simple_contract/src/main.nr @@ -0,0 +1,19 @@ +contract Foo { + fn double(x: Field) -> pub Field { + x * 2 + } + fn triple(x: Field) -> pub Field { + x * 3 + } + internal fn quadruple(x: Field) -> pub Field { + x * 4 + } + open internal fn skibbidy(x: Field) -> pub Field { + x * 5 + } + // Regression for issue #3344 + #[contract_library_method] + fn foo(x : u8) -> u8 { + x + } +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/attributes_multiple/Nargo.toml b/test_programs/compile_success_empty/attributes_multiple/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/attributes_multiple/Nargo.toml rename to test_programs/compile_success_empty/attributes_multiple/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/attributes_multiple/src/main.nr b/test_programs/compile_success_empty/attributes_multiple/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/attributes_multiple/src/main.nr rename to test_programs/compile_success_empty/attributes_multiple/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml b/test_programs/compile_success_empty/attributes_struct/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml rename to test_programs/compile_success_empty/attributes_struct/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/src/main.nr b/test_programs/compile_success_empty/attributes_struct/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/attributes_struct/src/main.nr rename to test_programs/compile_success_empty/attributes_struct/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/auto_deref/Nargo.toml b/test_programs/compile_success_empty/auto_deref/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/auto_deref/Nargo.toml rename to test_programs/compile_success_empty/auto_deref/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/auto_deref/src/main.nr b/test_programs/compile_success_empty/auto_deref/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/auto_deref/src/main.nr rename to test_programs/compile_success_empty/auto_deref/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_cast/Nargo.toml b/test_programs/compile_success_empty/brillig_cast/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_cast/Nargo.toml rename to test_programs/compile_success_empty/brillig_cast/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_cast/src/main.nr b/test_programs/compile_success_empty/brillig_cast/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_cast/src/main.nr rename to test_programs/compile_success_empty/brillig_cast/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/Nargo.toml b/test_programs/compile_success_empty/brillig_field_binary_operations/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/Nargo.toml rename to test_programs/compile_success_empty/brillig_field_binary_operations/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/Prover.toml b/test_programs/compile_success_empty/brillig_field_binary_operations/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/Prover.toml rename to test_programs/compile_success_empty/brillig_field_binary_operations/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/src/main.nr b/test_programs/compile_success_empty/brillig_field_binary_operations/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/src/main.nr rename to test_programs/compile_success_empty/brillig_field_binary_operations/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/Nargo.toml b/test_programs/compile_success_empty/brillig_integer_binary_operations/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/Nargo.toml rename to test_programs/compile_success_empty/brillig_integer_binary_operations/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/Prover.toml b/test_programs/compile_success_empty/brillig_integer_binary_operations/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/Prover.toml rename to test_programs/compile_success_empty/brillig_integer_binary_operations/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/src/main.nr b/test_programs/compile_success_empty/brillig_integer_binary_operations/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/src/main.nr rename to test_programs/compile_success_empty/brillig_integer_binary_operations/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/Nargo.toml b/test_programs/compile_success_empty/brillig_modulo/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/Nargo.toml rename to test_programs/compile_success_empty/brillig_modulo/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_579/Prover.toml b/test_programs/compile_success_empty/brillig_modulo/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/conditional_regression_579/Prover.toml rename to test_programs/compile_success_empty/brillig_modulo/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/src/main.nr b/test_programs/compile_success_empty/brillig_modulo/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/src/main.nr rename to test_programs/compile_success_empty/brillig_modulo/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_to_bits/Nargo.toml b/test_programs/compile_success_empty/brillig_to_bits/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_to_bits/Nargo.toml rename to test_programs/compile_success_empty/brillig_to_bits/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_to_bits/src/main.nr b/test_programs/compile_success_empty/brillig_to_bits/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/brillig_to_bits/src/main.nr rename to test_programs/compile_success_empty/brillig_to_bits/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/closure_explicit_types/Nargo.toml b/test_programs/compile_success_empty/closure_explicit_types/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/closure_explicit_types/Nargo.toml rename to test_programs/compile_success_empty/closure_explicit_types/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/closure_explicit_types/src/main.nr b/test_programs/compile_success_empty/closure_explicit_types/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/closure_explicit_types/src/main.nr rename to test_programs/compile_success_empty/closure_explicit_types/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/comptime_recursion_regression/Nargo.toml b/test_programs/compile_success_empty/comptime_recursion_regression/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/comptime_recursion_regression/Nargo.toml rename to test_programs/compile_success_empty/comptime_recursion_regression/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/comptime_recursion_regression/Prover.toml b/test_programs/compile_success_empty/comptime_recursion_regression/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/comptime_recursion_regression/Prover.toml rename to test_programs/compile_success_empty/comptime_recursion_regression/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/comptime_recursion_regression/src/main.nr b/test_programs/compile_success_empty/comptime_recursion_regression/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/comptime_recursion_regression/src/main.nr rename to test_programs/compile_success_empty/comptime_recursion_regression/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/comptime_sort/Nargo.toml b/test_programs/compile_success_empty/comptime_sort/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/comptime_sort/Nargo.toml rename to test_programs/compile_success_empty/comptime_sort/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/comptime_sort/src/main.nr b/test_programs/compile_success_empty/comptime_sort/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/comptime_sort/src/main.nr rename to test_programs/compile_success_empty/comptime_sort/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/Nargo.toml b/test_programs/compile_success_empty/conditional_regression_547/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/Nargo.toml rename to test_programs/compile_success_empty/conditional_regression_547/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/Prover.toml b/test_programs/compile_success_empty/conditional_regression_547/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/Prover.toml rename to test_programs/compile_success_empty/conditional_regression_547/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/src/main.nr b/test_programs/compile_success_empty/conditional_regression_547/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/src/main.nr rename to test_programs/compile_success_empty/conditional_regression_547/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_579/Nargo.toml b/test_programs/compile_success_empty/conditional_regression_579/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/conditional_regression_579/Nargo.toml rename to test_programs/compile_success_empty/conditional_regression_579/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/Prover.toml b/test_programs/compile_success_empty/conditional_regression_579/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/Prover.toml rename to test_programs/compile_success_empty/conditional_regression_579/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_579/src/main.nr b/test_programs/compile_success_empty/conditional_regression_579/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/conditional_regression_579/src/main.nr rename to test_programs/compile_success_empty/conditional_regression_579/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/Nargo.toml b/test_programs/compile_success_empty/conditional_regression_to_bits/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/Nargo.toml rename to test_programs/compile_success_empty/conditional_regression_to_bits/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/Prover.toml b/test_programs/compile_success_empty/conditional_regression_to_bits/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/Prover.toml rename to test_programs/compile_success_empty/conditional_regression_to_bits/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/src/main.nr b/test_programs/compile_success_empty/conditional_regression_to_bits/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/src/main.nr rename to test_programs/compile_success_empty/conditional_regression_to_bits/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/ec_baby_jubjub/Nargo.toml b/test_programs/compile_success_empty/ec_baby_jubjub/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/ec_baby_jubjub/Nargo.toml rename to test_programs/compile_success_empty/ec_baby_jubjub/Nargo.toml diff --git a/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr b/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr new file mode 100644 index 0000000000..becd3c8927 --- /dev/null +++ b/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr @@ -0,0 +1,218 @@ +// Tests may be checked against https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/tree/main/poc +use dep::std::ec::tecurve::affine::Curve as AffineCurve; +use dep::std::ec::tecurve::affine::Point as Gaffine; +use dep::std::ec::tecurve::curvegroup::Curve; +use dep::std::ec::tecurve::curvegroup::Point as G; + +use dep::std::ec::swcurve::affine::Point as SWGaffine; +use dep::std::ec::swcurve::curvegroup::Point as SWG; + +use dep::std::ec::montcurve::affine::Point as MGaffine; +use dep::std::ec::montcurve::curvegroup::Point as MG; + +fn main() { + // This test only makes sense if Field is the right prime field. + if 21888242871839275222246405745257275088548364400416034343698204186575808495617 == 0 { + // Define Baby Jubjub (ERC-2494) parameters in affine representation + let bjj_affine = AffineCurve::new( + 168700, + 168696, + Gaffine::new( + 995203441582195749578291179787384436505546430278305826713579947235728471134, + 5472060717959818805561601436314318772137091100104008585924551046643952123905 + ) + ); + // Test addition + let p1_affine = Gaffine::new( + 17777552123799933955779906779655732241715742912184938656739573121738514868268, + 2626589144620713026669568689430873010625803728049924121243784502389097019475 + ); + let p2_affine = Gaffine::new( + 16540640123574156134436876038791482806971768689494387082833631921987005038935, + 20819045374670962167435360035096875258406992893633759881276124905556507972311 + ); + + let p3_affine = bjj_affine.add(p1_affine, p2_affine); + assert( + p3_affine.eq( + Gaffine::new( + 7916061937171219682591368294088513039687205273691143098332585753343424131937, + 14035240266687799601661095864649209771790948434046947201833777492504781204499 + ) + ) + ); + // Test scalar multiplication + let p4_affine = bjj_affine.mul(2, p1_affine); + assert( + p4_affine.eq( + Gaffine::new( + 6890855772600357754907169075114257697580319025794532037257385534741338397365, + 4338620300185947561074059802482547481416142213883829469920100239455078257889 + ) + ) + ); + assert(p4_affine.eq(bjj_affine.bit_mul([0, 1], p1_affine))); + // Test subtraction + let p5_affine = bjj_affine.subtract(p3_affine, p3_affine); + assert(p5_affine.eq(Gaffine::zero())); + // Check that these points are on the curve + assert( + bjj_affine.contains(bjj_affine.gen) + & bjj_affine.contains(p1_affine) + & bjj_affine.contains(p2_affine) + & bjj_affine.contains(p3_affine) + & bjj_affine.contains(p4_affine) + & bjj_affine.contains(p5_affine) + ); + // Test CurveGroup equivalents + let bjj = bjj_affine.into_group(); // Baby Jubjub + let p1 = p1_affine.into_group(); + let p2 = p2_affine.into_group(); + let p3 = p3_affine.into_group(); + let p4 = p4_affine.into_group(); + let p5 = p5_affine.into_group(); + // Test addition + assert(p3.eq(bjj.add(p1, p2))); + // Test scalar multiplication + assert(p4.eq(bjj.mul(2, p1))); + assert(p4.eq(bjj.bit_mul([0, 1], p1))); + // Test subtraction + assert(G::zero().eq(bjj.subtract(p3, p3))); + assert(p5.eq(G::zero())); + // Check that these points are on the curve + assert( + bjj.contains(bjj.gen) + & bjj.contains(p1) + & bjj.contains(p2) + & bjj.contains(p3) + & bjj.contains(p4) + & bjj.contains(p5) + ); + // Test SWCurve equivalents of the above + // First the affine representation + let bjj_swcurve_affine = bjj_affine.into_swcurve(); + + let p1_swcurve_affine = bjj_affine.map_into_swcurve(p1_affine); + let p2_swcurve_affine = bjj_affine.map_into_swcurve(p2_affine); + let p3_swcurve_affine = bjj_affine.map_into_swcurve(p3_affine); + let p4_swcurve_affine = bjj_affine.map_into_swcurve(p4_affine); + let p5_swcurve_affine = bjj_affine.map_into_swcurve(p5_affine); + // Addition + assert(p3_swcurve_affine.eq(bjj_swcurve_affine.add(p1_swcurve_affine, p2_swcurve_affine))); + // Doubling + assert(p4_swcurve_affine.eq(bjj_swcurve_affine.mul(2, p1_swcurve_affine))); + assert(p4_swcurve_affine.eq(bjj_swcurve_affine.bit_mul([0, 1], p1_swcurve_affine))); + // Subtraction + assert(SWGaffine::zero().eq(bjj_swcurve_affine.subtract(p3_swcurve_affine, p3_swcurve_affine))); + assert(p5_swcurve_affine.eq(SWGaffine::zero())); + // Check that these points are on the curve + assert( + bjj_swcurve_affine.contains(bjj_swcurve_affine.gen) + & bjj_swcurve_affine.contains(p1_swcurve_affine) + & bjj_swcurve_affine.contains(p2_swcurve_affine) + & bjj_swcurve_affine.contains(p3_swcurve_affine) + & bjj_swcurve_affine.contains(p4_swcurve_affine) + & bjj_swcurve_affine.contains(p5_swcurve_affine) + ); + // Then the CurveGroup representation + let bjj_swcurve = bjj.into_swcurve(); + + let p1_swcurve = bjj.map_into_swcurve(p1); + let p2_swcurve = bjj.map_into_swcurve(p2); + let p3_swcurve = bjj.map_into_swcurve(p3); + let p4_swcurve = bjj.map_into_swcurve(p4); + let p5_swcurve = bjj.map_into_swcurve(p5); + // Addition + assert(p3_swcurve.eq(bjj_swcurve.add(p1_swcurve, p2_swcurve))); + // Doubling + assert(p4_swcurve.eq(bjj_swcurve.mul(2, p1_swcurve))); + assert(p4_swcurve.eq(bjj_swcurve.bit_mul([0, 1], p1_swcurve))); + // Subtraction + assert(SWG::zero().eq(bjj_swcurve.subtract(p3_swcurve, p3_swcurve))); + assert(p5_swcurve.eq(SWG::zero())); + // Check that these points are on the curve + assert( + bjj_swcurve.contains(bjj_swcurve.gen) + & bjj_swcurve.contains(p1_swcurve) + & bjj_swcurve.contains(p2_swcurve) + & bjj_swcurve.contains(p3_swcurve) + & bjj_swcurve.contains(p4_swcurve) + & bjj_swcurve.contains(p5_swcurve) + ); + // Test MontCurve conversions + // First the affine representation + let bjj_montcurve_affine = bjj_affine.into_montcurve(); + + let p1_montcurve_affine = p1_affine.into_montcurve(); + let p2_montcurve_affine = p2_affine.into_montcurve(); + let p3_montcurve_affine = p3_affine.into_montcurve(); + let p4_montcurve_affine = p4_affine.into_montcurve(); + let p5_montcurve_affine = p5_affine.into_montcurve(); + // Addition + assert(p3_montcurve_affine.eq(bjj_montcurve_affine.add(p1_montcurve_affine, p2_montcurve_affine))); + // Doubling + assert(p4_montcurve_affine.eq(bjj_montcurve_affine.mul(2, p1_montcurve_affine))); + assert(p4_montcurve_affine.eq(bjj_montcurve_affine.bit_mul([0, 1], p1_montcurve_affine))); + // Subtraction + assert(MGaffine::zero().eq(bjj_montcurve_affine.subtract(p3_montcurve_affine, p3_montcurve_affine))); + assert(p5_montcurve_affine.eq(MGaffine::zero())); + // Check that these points are on the curve + assert( + bjj_montcurve_affine.contains(bjj_montcurve_affine.gen) + & bjj_montcurve_affine.contains(p1_montcurve_affine) + & bjj_montcurve_affine.contains(p2_montcurve_affine) + & bjj_montcurve_affine.contains(p3_montcurve_affine) + & bjj_montcurve_affine.contains(p4_montcurve_affine) + & bjj_montcurve_affine.contains(p5_montcurve_affine) + ); + // Then the CurveGroup representation + let bjj_montcurve = bjj.into_montcurve(); + + let p1_montcurve = p1_montcurve_affine.into_group(); + let p2_montcurve = p2_montcurve_affine.into_group(); + let p3_montcurve = p3_montcurve_affine.into_group(); + let p4_montcurve = p4_montcurve_affine.into_group(); + let p5_montcurve = p5_montcurve_affine.into_group(); + // Addition + assert(p3_montcurve.eq(bjj_montcurve.add(p1_montcurve, p2_montcurve))); + // Doubling + assert(p4_montcurve.eq(bjj_montcurve.mul(2, p1_montcurve))); + assert(p4_montcurve.eq(bjj_montcurve.bit_mul([0, 1], p1_montcurve))); + // Subtraction + assert(MG::zero().eq(bjj_montcurve.subtract(p3_montcurve, p3_montcurve))); + assert(p5_montcurve.eq(MG::zero())); + // Check that these points are on the curve + assert( + bjj_montcurve.contains(bjj_montcurve.gen) + & bjj_montcurve.contains(p1_montcurve) + & bjj_montcurve.contains(p2_montcurve) + & bjj_montcurve.contains(p3_montcurve) + & bjj_montcurve.contains(p4_montcurve) + & bjj_montcurve.contains(p5_montcurve) + ); + // Elligator 2 map-to-curve + let ell2_pt_map = bjj_affine.elligator2_map(27); + + assert( + ell2_pt_map.eq( + MGaffine::new( + 7972459279704486422145701269802978968072470631857513331988813812334797879121, + 8142420778878030219043334189293412482212146646099536952861607542822144507872 + ).into_tecurve() + ) + ); + // SWU map-to-curve + let swu_pt_map = bjj_affine.swu_map(5, 27); + + assert( + swu_pt_map.eq( + bjj_affine.map_from_swcurve( + SWGaffine::new( + 2162719247815120009132293839392097468339661471129795280520343931405114293888, + 5341392251743377373758788728206293080122949448990104760111875914082289313973 + ) + ) + ) + ); + } +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/generators/Nargo.toml b/test_programs/compile_success_empty/generators/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/generators/Nargo.toml rename to test_programs/compile_success_empty/generators/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/generators/src/main.nr b/test_programs/compile_success_empty/generators/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/generators/src/main.nr rename to test_programs/compile_success_empty/generators/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/higher_order_fn_selector/Nargo.toml b/test_programs/compile_success_empty/higher_order_fn_selector/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/higher_order_fn_selector/Nargo.toml rename to test_programs/compile_success_empty/higher_order_fn_selector/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/higher_order_fn_selector/src/main.nr b/test_programs/compile_success_empty/higher_order_fn_selector/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/higher_order_fn_selector/src/main.nr rename to test_programs/compile_success_empty/higher_order_fn_selector/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/impl_with_where_clause/Nargo.toml b/test_programs/compile_success_empty/impl_with_where_clause/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/impl_with_where_clause/Nargo.toml rename to test_programs/compile_success_empty/impl_with_where_clause/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/impl_with_where_clause/src/main.nr b/test_programs/compile_success_empty/impl_with_where_clause/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/impl_with_where_clause/src/main.nr rename to test_programs/compile_success_empty/impl_with_where_clause/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/inner_outer_cl/Nargo.toml b/test_programs/compile_success_empty/inner_outer_cl/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/inner_outer_cl/Nargo.toml rename to test_programs/compile_success_empty/inner_outer_cl/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/inner_outer_cl/src/main.nr b/test_programs/compile_success_empty/inner_outer_cl/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/inner_outer_cl/src/main.nr rename to test_programs/compile_success_empty/inner_outer_cl/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/Nargo.toml b/test_programs/compile_success_empty/instruction_deduplication/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/Nargo.toml rename to test_programs/compile_success_empty/instruction_deduplication/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/let_stmt/Prover.toml b/test_programs/compile_success_empty/instruction_deduplication/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/let_stmt/Prover.toml rename to test_programs/compile_success_empty/instruction_deduplication/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/src/main.nr b/test_programs/compile_success_empty/instruction_deduplication/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/src/main.nr rename to test_programs/compile_success_empty/instruction_deduplication/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/intrinsic_die/Nargo.toml b/test_programs/compile_success_empty/intrinsic_die/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/intrinsic_die/Nargo.toml rename to test_programs/compile_success_empty/intrinsic_die/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/intrinsic_die/src/main.nr b/test_programs/compile_success_empty/intrinsic_die/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/intrinsic_die/src/main.nr rename to test_programs/compile_success_empty/intrinsic_die/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/let_stmt/Nargo.toml b/test_programs/compile_success_empty/let_stmt/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/let_stmt/Nargo.toml rename to test_programs/compile_success_empty/let_stmt/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/numeric_generics/Prover.toml b/test_programs/compile_success_empty/let_stmt/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/numeric_generics/Prover.toml rename to test_programs/compile_success_empty/let_stmt/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/let_stmt/src/main.nr b/test_programs/compile_success_empty/let_stmt/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/let_stmt/src/main.nr rename to test_programs/compile_success_empty/let_stmt/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/main_return/Nargo.toml b/test_programs/compile_success_empty/main_return/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/main_return/Nargo.toml rename to test_programs/compile_success_empty/main_return/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/main_return/Prover.toml b/test_programs/compile_success_empty/main_return/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/main_return/Prover.toml rename to test_programs/compile_success_empty/main_return/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/main_return/src/main.nr b/test_programs/compile_success_empty/main_return/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/main_return/src/main.nr rename to test_programs/compile_success_empty/main_return/src/main.nr diff --git a/test_programs/compile_success_empty/method_call_regression/Nargo.toml b/test_programs/compile_success_empty/method_call_regression/Nargo.toml new file mode 100644 index 0000000000..92c9b94200 --- /dev/null +++ b/test_programs/compile_success_empty/method_call_regression/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "short" +type = "bin" +authors = [""] +compiler_version = ">=0.19.4" + +[dependencies] \ No newline at end of file diff --git a/test_programs/compile_success_empty/method_call_regression/src/main.nr b/test_programs/compile_success_empty/method_call_regression/src/main.nr new file mode 100644 index 0000000000..8bb7ebcac4 --- /dev/null +++ b/test_programs/compile_success_empty/method_call_regression/src/main.nr @@ -0,0 +1,25 @@ +use dep::std; + +fn main() { + // s: Struct + let s = Struct { b: () }; + // Regression for #3089 + s.foo(); +} + +struct Struct { b: B } + +// Before the fix, this candidate is searched first, binding ? to `u8` permanently. +impl Struct { + fn foo(self) {} +} + +// Then this candidate would be searched next but would not be a valid +// candidate since `Struct` != `Struct`. +// +// With the fix, the type of `s` correctly no longer changes until a +// method is actually selected. So this candidate is now valid since +// `Struct` unifies with `Struct` with `? = u32`. +impl Struct { + fn foo(self) {} +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/numeric_generics/Nargo.toml b/test_programs/compile_success_empty/numeric_generics/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/numeric_generics/Nargo.toml rename to test_programs/compile_success_empty/numeric_generics/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/references_aliasing/Prover.toml b/test_programs/compile_success_empty/numeric_generics/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/references_aliasing/Prover.toml rename to test_programs/compile_success_empty/numeric_generics/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/numeric_generics/src/main.nr b/test_programs/compile_success_empty/numeric_generics/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/numeric_generics/src/main.nr rename to test_programs/compile_success_empty/numeric_generics/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/option/Nargo.toml b/test_programs/compile_success_empty/option/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/option/Nargo.toml rename to test_programs/compile_success_empty/option/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/option/src/main.nr b/test_programs/compile_success_empty/option/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/option/src/main.nr rename to test_programs/compile_success_empty/option/src/main.nr diff --git a/test_programs/compile_success_empty/raw_string/Nargo.toml b/test_programs/compile_success_empty/raw_string/Nargo.toml new file mode 100644 index 0000000000..81147e65f3 --- /dev/null +++ b/test_programs/compile_success_empty/raw_string/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "raw_string" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/raw_string/src/main.nr b/test_programs/compile_success_empty/raw_string/src/main.nr new file mode 100644 index 0000000000..ad8dfe82ae --- /dev/null +++ b/test_programs/compile_success_empty/raw_string/src/main.nr @@ -0,0 +1,13 @@ +global D = r#####"Hello "world""#####; + +fn main() { + let a = "Hello \"world\""; + let b = r#"Hello "world""#; + let c = r##"Hello "world""##; + assert(a == b); + assert(b == c); + assert(c == D); + let x = r#"Hello World"#; + let y = r"Hello World"; + assert(x == y); +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/references_aliasing/Nargo.toml b/test_programs/compile_success_empty/references_aliasing/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/references_aliasing/Nargo.toml rename to test_programs/compile_success_empty/references_aliasing/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/Prover.toml b/test_programs/compile_success_empty/references_aliasing/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/Prover.toml rename to test_programs/compile_success_empty/references_aliasing/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/references_aliasing/src/main.nr b/test_programs/compile_success_empty/references_aliasing/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/references_aliasing/src/main.nr rename to test_programs/compile_success_empty/references_aliasing/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/regression_2099/Nargo.toml b/test_programs/compile_success_empty/regression_2099/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/regression_2099/Nargo.toml rename to test_programs/compile_success_empty/regression_2099/Nargo.toml diff --git a/test_programs/compile_success_empty/regression_2099/src/main.nr b/test_programs/compile_success_empty/regression_2099/src/main.nr new file mode 100644 index 0000000000..f92373ce63 --- /dev/null +++ b/test_programs/compile_success_empty/regression_2099/src/main.nr @@ -0,0 +1,42 @@ +use dep::std::ec::tecurve::affine::Curve as AffineCurve; +use dep::std::ec::tecurve::affine::Point as Gaffine; +use dep::std::ec::tecurve::curvegroup::Curve; +use dep::std::ec::tecurve::curvegroup::Point as G; + +use dep::std::ec::swcurve::affine::Point as SWGaffine; +use dep::std::ec::swcurve::curvegroup::Point as SWG; + +use dep::std::ec::montcurve::affine::Point as MGaffine; +use dep::std::ec::montcurve::curvegroup::Point as MG; + +fn main() { + // Define Baby Jubjub (ERC-2494) parameters in affine representation + let bjj_affine = AffineCurve::new( + 168700, + 168696, + Gaffine::new( + 995203441582195749578291179787384436505546430278305826713579947235728471134, + 5472060717959818805561601436314318772137091100104008585924551046643952123905 + ) + ); + // Test addition + let p1_affine = Gaffine::new( + 17777552123799933955779906779655732241715742912184938656739573121738514868268, + 2626589144620713026669568689430873010625803728049924121243784502389097019475 + ); + let p2_affine = Gaffine::new( + 16540640123574156134436876038791482806971768689494387082833631921987005038935, + 20819045374670962167435360035096875258406992893633759881276124905556507972311 + ); + let _p3_affine = bjj_affine.add(p1_affine, p2_affine); + // Test SWCurve equivalents of the above + // First the affine representation + let bjj_swcurve_affine = bjj_affine.into_swcurve(); + + let p1_swcurve_affine = bjj_affine.map_into_swcurve(p1_affine); + let p2_swcurve_affine = bjj_affine.map_into_swcurve(p2_affine); + + let _p3_swcurve_affine_from_add = bjj_swcurve_affine.add(p1_swcurve_affine, p2_swcurve_affine); + // Check that these points are on the curve + assert(bjj_swcurve_affine.contains(p1_swcurve_affine)); +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/Nargo.toml b/test_programs/compile_success_empty/ret_fn_ret_cl/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/Nargo.toml rename to test_programs/compile_success_empty/ret_fn_ret_cl/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/Prover.toml b/test_programs/compile_success_empty/ret_fn_ret_cl/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/Prover.toml rename to test_programs/compile_success_empty/ret_fn_ret_cl/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/src/main.nr b/test_programs/compile_success_empty/ret_fn_ret_cl/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/src/main.nr rename to test_programs/compile_success_empty/ret_fn_ret_cl/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_array_param/Nargo.toml b/test_programs/compile_success_empty/simple_array_param/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/simple_array_param/Nargo.toml rename to test_programs/compile_success_empty/simple_array_param/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_array_param/Prover.toml b/test_programs/compile_success_empty/simple_array_param/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/simple_array_param/Prover.toml rename to test_programs/compile_success_empty/simple_array_param/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_array_param/src/main.nr b/test_programs/compile_success_empty/simple_array_param/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/simple_array_param/src/main.nr rename to test_programs/compile_success_empty/simple_array_param/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/Nargo.toml b/test_programs/compile_success_empty/simple_program_no_body/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/Nargo.toml rename to test_programs/compile_success_empty/simple_program_no_body/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/Prover.toml b/test_programs/compile_success_empty/simple_program_no_body/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/Prover.toml rename to test_programs/compile_success_empty/simple_program_no_body/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/src/main.nr b/test_programs/compile_success_empty/simple_program_no_body/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/src/main.nr rename to test_programs/compile_success_empty/simple_program_no_body/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_range/Nargo.toml b/test_programs/compile_success_empty/simple_range/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/simple_range/Nargo.toml rename to test_programs/compile_success_empty/simple_range/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_range/Prover.toml b/test_programs/compile_success_empty/simple_range/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/simple_range/Prover.toml rename to test_programs/compile_success_empty/simple_range/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_range/src/main.nr b/test_programs/compile_success_empty/simple_range/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/simple_range/src/main.nr rename to test_programs/compile_success_empty/simple_range/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/specialization/Nargo.toml b/test_programs/compile_success_empty/specialization/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/specialization/Nargo.toml rename to test_programs/compile_success_empty/specialization/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/specialization/src/main.nr b/test_programs/compile_success_empty/specialization/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/specialization/src/main.nr rename to test_programs/compile_success_empty/specialization/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/str_as_bytes/Nargo.toml b/test_programs/compile_success_empty/str_as_bytes/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/str_as_bytes/Nargo.toml rename to test_programs/compile_success_empty/str_as_bytes/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/str_as_bytes/src/main.nr b/test_programs/compile_success_empty/str_as_bytes/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/str_as_bytes/src/main.nr rename to test_programs/compile_success_empty/str_as_bytes/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/to_bits/Nargo.toml b/test_programs/compile_success_empty/to_bits/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/to_bits/Nargo.toml rename to test_programs/compile_success_empty/to_bits/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/to_bits/src/main.nr b/test_programs/compile_success_empty/to_bits/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/to_bits/src/main.nr rename to test_programs/compile_success_empty/to_bits/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/Nargo.toml b/test_programs/compile_success_empty/trait_allowed_item_name_matches/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/Nargo.toml rename to test_programs/compile_success_empty/trait_allowed_item_name_matches/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_associated_member_names_clashes/Prover.toml b/test_programs/compile_success_empty/trait_allowed_item_name_matches/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_associated_member_names_clashes/Prover.toml rename to test_programs/compile_success_empty/trait_allowed_item_name_matches/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/src/main.nr b/test_programs/compile_success_empty/trait_allowed_item_name_matches/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/src/main.nr rename to test_programs/compile_success_empty/trait_allowed_item_name_matches/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_associated_member_names_clashes/Nargo.toml b/test_programs/compile_success_empty/trait_associated_member_names_clashes/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_associated_member_names_clashes/Nargo.toml rename to test_programs/compile_success_empty/trait_associated_member_names_clashes/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/Prover.toml b/test_programs/compile_success_empty/trait_associated_member_names_clashes/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/Prover.toml rename to test_programs/compile_success_empty/trait_associated_member_names_clashes/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_associated_member_names_clashes/src/main.nr b/test_programs/compile_success_empty/trait_associated_member_names_clashes/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_associated_member_names_clashes/src/main.nr rename to test_programs/compile_success_empty/trait_associated_member_names_clashes/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_default_implementation/Nargo.toml b/test_programs/compile_success_empty/trait_default_implementation/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_default_implementation/Nargo.toml rename to test_programs/compile_success_empty/trait_default_implementation/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_default_implementation/Prover.toml b/test_programs/compile_success_empty/trait_default_implementation/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_default_implementation/Prover.toml rename to test_programs/compile_success_empty/trait_default_implementation/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_default_implementation/src/main.nr b/test_programs/compile_success_empty/trait_default_implementation/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_default_implementation/src/main.nr rename to test_programs/compile_success_empty/trait_default_implementation/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/Nargo.toml b/test_programs/compile_success_empty/trait_function_calls/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/Nargo.toml rename to test_programs/compile_success_empty/trait_function_calls/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/Prover.toml b/test_programs/compile_success_empty/trait_function_calls/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/Prover.toml rename to test_programs/compile_success_empty/trait_function_calls/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/src/main.nr b/test_programs/compile_success_empty/trait_function_calls/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/src/main.nr rename to test_programs/compile_success_empty/trait_function_calls/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_generics/Nargo.toml b/test_programs/compile_success_empty/trait_generics/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_generics/Nargo.toml rename to test_programs/compile_success_empty/trait_generics/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_generics/src/main.nr b/test_programs/compile_success_empty/trait_generics/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_generics/src/main.nr rename to test_programs/compile_success_empty/trait_generics/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/Nargo.toml b/test_programs/compile_success_empty/trait_multi_module_test/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/Nargo.toml rename to test_programs/compile_success_empty/trait_multi_module_test/Nargo.toml diff --git a/tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/Prover.toml b/test_programs/compile_success_empty/trait_multi_module_test/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/Prover.toml rename to test_programs/compile_success_empty/trait_multi_module_test/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/main.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/main.nr rename to test_programs/compile_success_empty/trait_multi_module_test/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module1.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module1.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module1.nr rename to test_programs/compile_success_empty/trait_multi_module_test/src/module1.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module2.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module2.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module2.nr rename to test_programs/compile_success_empty/trait_multi_module_test/src/module2.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module3.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module3.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module3.nr rename to test_programs/compile_success_empty/trait_multi_module_test/src/module3.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module4.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module4.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module4.nr rename to test_programs/compile_success_empty/trait_multi_module_test/src/module4.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module5.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module5.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module5.nr rename to test_programs/compile_success_empty/trait_multi_module_test/src/module5.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module6.nr b/test_programs/compile_success_empty/trait_multi_module_test/src/module6.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module6.nr rename to test_programs/compile_success_empty/trait_multi_module_test/src/module6.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/Nargo.toml b/test_programs/compile_success_empty/trait_override_implementation/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/Nargo.toml rename to test_programs/compile_success_empty/trait_override_implementation/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/Prover.toml b/test_programs/compile_success_empty/trait_override_implementation/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/Prover.toml rename to test_programs/compile_success_empty/trait_override_implementation/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/src/main.nr b/test_programs/compile_success_empty/trait_override_implementation/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/src/main.nr rename to test_programs/compile_success_empty/trait_override_implementation/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_static_methods/Nargo.toml b/test_programs/compile_success_empty/trait_static_methods/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_static_methods/Nargo.toml rename to test_programs/compile_success_empty/trait_static_methods/Nargo.toml diff --git a/test_programs/compile_success_empty/trait_static_methods/src/main.nr b/test_programs/compile_success_empty/trait_static_methods/src/main.nr new file mode 100644 index 0000000000..838e47ee82 --- /dev/null +++ b/test_programs/compile_success_empty/trait_static_methods/src/main.nr @@ -0,0 +1,64 @@ +trait ATrait { + fn asd() -> Self; + + fn static_method() -> Field { + Self::static_method_2() + } + + fn static_method_2() -> Field { + 100 + } +} + +struct Foo { + x: Field +} +impl ATrait for Foo { + fn asd() -> Self { + // This should pass as Self should be bound to Foo while typechecking this + Foo{x: 100} + } +} + +struct Bar { + x: Field +} +impl ATrait for Bar { + // The trait method is declared as returning `Self` + // but explicitly specifying the type in the impl should work + fn asd() -> Bar { + Bar{x: 100} + } + + fn static_method_2() -> Field { + 200 + } +} + +fn main() { + assert(Foo::static_method() == 100); + assert(Bar::static_method() == 200); + + // Regression for #3773 + let zero: Field = MyDefault::my_default(); + assert(zero == 0); +} + +trait MyDefault { + fn my_default() -> Self; +} + +// This impl is first, so if the type directed search picks the first impl +// instead of the correct Field impl below, we'll get a panic in SSA from +// a type mismatch. +impl MyDefault for (Field, Field) { + fn my_default() -> (Field, Field) { + (0, 0) + } +} + +impl MyDefault for Field { + fn my_default() -> Field { + 0 + } +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/Nargo.toml b/test_programs/compile_success_empty/trait_where_clause/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/Nargo.toml rename to test_programs/compile_success_empty/trait_where_clause/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/src/main.nr b/test_programs/compile_success_empty/trait_where_clause/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/src/main.nr rename to test_programs/compile_success_empty/trait_where_clause/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/src/the_trait.nr b/test_programs/compile_success_empty/trait_where_clause/src/the_trait.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/src/the_trait.nr rename to test_programs/compile_success_empty/trait_where_clause/src/the_trait.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/traits/Nargo.toml b/test_programs/compile_success_empty/traits/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/traits/Nargo.toml rename to test_programs/compile_success_empty/traits/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/traits/Prover.toml b/test_programs/compile_success_empty/traits/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/traits/Prover.toml rename to test_programs/compile_success_empty/traits/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/traits/src/main.nr b/test_programs/compile_success_empty/traits/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/traits/src/main.nr rename to test_programs/compile_success_empty/traits/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/unary_operators/Nargo.toml b/test_programs/compile_success_empty/unary_operators/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/unary_operators/Nargo.toml rename to test_programs/compile_success_empty/unary_operators/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/unary_operators/src/main.nr b/test_programs/compile_success_empty/unary_operators/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/unary_operators/src/main.nr rename to test_programs/compile_success_empty/unary_operators/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/unconstrained_empty/Nargo.toml b/test_programs/compile_success_empty/unconstrained_empty/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/unconstrained_empty/Nargo.toml rename to test_programs/compile_success_empty/unconstrained_empty/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/unconstrained_empty/src/main.nr b/test_programs/compile_success_empty/unconstrained_empty/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/unconstrained_empty/src/main.nr rename to test_programs/compile_success_empty/unconstrained_empty/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/unit/Nargo.toml b/test_programs/compile_success_empty/unit/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/unit/Nargo.toml rename to test_programs/compile_success_empty/unit/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/unit/src/main.nr b/test_programs/compile_success_empty/unit/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/unit/src/main.nr rename to test_programs/compile_success_empty/unit/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/unused_variables/Nargo.toml b/test_programs/compile_success_empty/unused_variables/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/unused_variables/Nargo.toml rename to test_programs/compile_success_empty/unused_variables/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/unused_variables/src/main.nr b/test_programs/compile_success_empty/unused_variables/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/unused_variables/src/main.nr rename to test_programs/compile_success_empty/unused_variables/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/vectors/Nargo.toml b/test_programs/compile_success_empty/vectors/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/vectors/Nargo.toml rename to test_programs/compile_success_empty/vectors/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/vectors/Prover.toml b/test_programs/compile_success_empty/vectors/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/vectors/Prover.toml rename to test_programs/compile_success_empty/vectors/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/vectors/src/main.nr b/test_programs/compile_success_empty/vectors/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/vectors/src/main.nr rename to test_programs/compile_success_empty/vectors/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/Nargo.toml b/test_programs/compile_success_empty/workspace_reexport_bug/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/Nargo.toml rename to test_programs/compile_success_empty/workspace_reexport_bug/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/binary/Nargo.toml b/test_programs/compile_success_empty/workspace_reexport_bug/binary/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/binary/Nargo.toml rename to test_programs/compile_success_empty/workspace_reexport_bug/binary/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/binary/src/main.nr b/test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/binary/src/main.nr rename to test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library/Nargo.toml b/test_programs/compile_success_empty/workspace_reexport_bug/library/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library/Nargo.toml rename to test_programs/compile_success_empty/workspace_reexport_bug/library/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library/src/lib.nr b/test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library/src/lib.nr rename to test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library2/Nargo.toml b/test_programs/compile_success_empty/workspace_reexport_bug/library2/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library2/Nargo.toml rename to test_programs/compile_success_empty/workspace_reexport_bug/library2/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library2/src/lib.nr b/test_programs/compile_success_empty/workspace_reexport_bug/library2/src/lib.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library2/src/lib.nr rename to test_programs/compile_success_empty/workspace_reexport_bug/library2/src/lib.nr diff --git a/tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/Nargo.toml b/test_programs/execution_success/1327_concrete_in_generic/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/Nargo.toml rename to test_programs/execution_success/1327_concrete_in_generic/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/Prover.toml b/test_programs/execution_success/1327_concrete_in_generic/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/Prover.toml rename to test_programs/execution_success/1327_concrete_in_generic/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/src/main.nr b/test_programs/execution_success/1327_concrete_in_generic/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/src/main.nr rename to test_programs/execution_success/1327_concrete_in_generic/src/main.nr diff --git a/test_programs/execution_success/1_mul/Nargo.toml b/test_programs/execution_success/1_mul/Nargo.toml new file mode 100644 index 0000000000..94b36157cc --- /dev/null +++ b/test_programs/execution_success/1_mul/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "1_mul" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/1_mul/Prover.toml b/test_programs/execution_success/1_mul/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/1_mul/Prover.toml rename to test_programs/execution_success/1_mul/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/1_mul/src/main.nr b/test_programs/execution_success/1_mul/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/1_mul/src/main.nr rename to test_programs/execution_success/1_mul/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/2_div/Nargo.toml b/test_programs/execution_success/2_div/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/2_div/Nargo.toml rename to test_programs/execution_success/2_div/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/2_div/Prover.toml b/test_programs/execution_success/2_div/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/2_div/Prover.toml rename to test_programs/execution_success/2_div/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/2_div/src/main.nr b/test_programs/execution_success/2_div/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/2_div/src/main.nr rename to test_programs/execution_success/2_div/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/3_add/Nargo.toml b/test_programs/execution_success/3_add/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/3_add/Nargo.toml rename to test_programs/execution_success/3_add/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/3_add/Prover.toml b/test_programs/execution_success/3_add/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/3_add/Prover.toml rename to test_programs/execution_success/3_add/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/3_add/src/main.nr b/test_programs/execution_success/3_add/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/3_add/src/main.nr rename to test_programs/execution_success/3_add/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/4_sub/Nargo.toml b/test_programs/execution_success/4_sub/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/4_sub/Nargo.toml rename to test_programs/execution_success/4_sub/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/4_sub/Prover.toml b/test_programs/execution_success/4_sub/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/4_sub/Prover.toml rename to test_programs/execution_success/4_sub/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/4_sub/src/main.nr b/test_programs/execution_success/4_sub/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/4_sub/src/main.nr rename to test_programs/execution_success/4_sub/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/5_over/Nargo.toml b/test_programs/execution_success/5_over/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/5_over/Nargo.toml rename to test_programs/execution_success/5_over/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/5_over/Prover.toml b/test_programs/execution_success/5_over/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/5_over/Prover.toml rename to test_programs/execution_success/5_over/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/5_over/src/main.nr b/test_programs/execution_success/5_over/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/5_over/src/main.nr rename to test_programs/execution_success/5_over/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/6/Nargo.toml b/test_programs/execution_success/6/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/6/Nargo.toml rename to test_programs/execution_success/6/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/6/Prover.toml b/test_programs/execution_success/6/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/6/Prover.toml rename to test_programs/execution_success/6/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/6/src/main.nr b/test_programs/execution_success/6/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/6/src/main.nr rename to test_programs/execution_success/6/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/6_array/Nargo.toml b/test_programs/execution_success/6_array/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/6_array/Nargo.toml rename to test_programs/execution_success/6_array/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/6_array/Prover.toml b/test_programs/execution_success/6_array/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/6_array/Prover.toml rename to test_programs/execution_success/6_array/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/6_array/src/main.nr b/test_programs/execution_success/6_array/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/6_array/src/main.nr rename to test_programs/execution_success/6_array/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/7/Nargo.toml b/test_programs/execution_success/7/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/7/Nargo.toml rename to test_programs/execution_success/7/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/7/Prover.toml b/test_programs/execution_success/7/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/7/Prover.toml rename to test_programs/execution_success/7/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/7/src/main.nr b/test_programs/execution_success/7/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/7/src/main.nr rename to test_programs/execution_success/7/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/7_function/Nargo.toml b/test_programs/execution_success/7_function/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/7_function/Nargo.toml rename to test_programs/execution_success/7_function/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/7_function/Prover.toml b/test_programs/execution_success/7_function/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/7_function/Prover.toml rename to test_programs/execution_success/7_function/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/7_function/src/main.nr b/test_programs/execution_success/7_function/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/7_function/src/main.nr rename to test_programs/execution_success/7_function/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/Nargo.toml b/test_programs/execution_success/arithmetic_binary_operations/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/Nargo.toml rename to test_programs/execution_success/arithmetic_binary_operations/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/Prover.toml b/test_programs/execution_success/arithmetic_binary_operations/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/Prover.toml rename to test_programs/execution_success/arithmetic_binary_operations/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/src/main.nr b/test_programs/execution_success/arithmetic_binary_operations/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/src/main.nr rename to test_programs/execution_success/arithmetic_binary_operations/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/array_dynamic/Nargo.toml b/test_programs/execution_success/array_dynamic/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_dynamic/Nargo.toml rename to test_programs/execution_success/array_dynamic/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/array_dynamic/Prover.toml b/test_programs/execution_success/array_dynamic/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_dynamic/Prover.toml rename to test_programs/execution_success/array_dynamic/Prover.toml diff --git a/test_programs/execution_success/array_dynamic/src/main.nr b/test_programs/execution_success/array_dynamic/src/main.nr new file mode 100644 index 0000000000..dde7bacc45 --- /dev/null +++ b/test_programs/execution_success/array_dynamic/src/main.nr @@ -0,0 +1,38 @@ +fn main( + x: [u32; 5], + mut z: u32, + t: u32, + index: [Field;5], + index2: [Field;5], + offset: Field, + sublen: Field +) { + let idx = (z - 5 * t - 5) as Field; + //dynamic array test + dyn_array(x, idx, idx - 3); + //regression for issue 1283 + let mut s = 0; + let x3 = [246, 159, 32, 176, 8]; + for i in 0..5 { + s += x3[index[i]]; + } + assert(s != 0); + + if 3 < (sublen as u32) { + assert(index[offset + 3] == index2[3]); + } +} + +fn dyn_array(mut x: [u32; 5], y: Field, z: Field) { + assert(x[y] == 111); + assert(x[z] == 101); + x[z] = 0; + assert(x[y] == 111); + assert(x[1] == 0); + if y as u32 < 10 { + x[y] = x[y] - 2; + } else { + x[y] = 0; + } + assert(x[4] == 109); +} diff --git a/tooling/nargo_cli/tests/execution_success/array_eq/Nargo.toml b/test_programs/execution_success/array_eq/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_eq/Nargo.toml rename to test_programs/execution_success/array_eq/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/array_eq/Prover.toml b/test_programs/execution_success/array_eq/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_eq/Prover.toml rename to test_programs/execution_success/array_eq/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/array_eq/src/main.nr b/test_programs/execution_success/array_eq/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_eq/src/main.nr rename to test_programs/execution_success/array_eq/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/array_len/Nargo.toml b/test_programs/execution_success/array_len/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_len/Nargo.toml rename to test_programs/execution_success/array_len/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/array_len/Prover.toml b/test_programs/execution_success/array_len/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_len/Prover.toml rename to test_programs/execution_success/array_len/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/array_len/src/main.nr b/test_programs/execution_success/array_len/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_len/src/main.nr rename to test_programs/execution_success/array_len/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/array_neq/Nargo.toml b/test_programs/execution_success/array_neq/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_neq/Nargo.toml rename to test_programs/execution_success/array_neq/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/array_neq/Prover.toml b/test_programs/execution_success/array_neq/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_neq/Prover.toml rename to test_programs/execution_success/array_neq/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/array_neq/src/main.nr b/test_programs/execution_success/array_neq/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_neq/src/main.nr rename to test_programs/execution_success/array_neq/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/array_sort/Nargo.toml b/test_programs/execution_success/array_sort/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_sort/Nargo.toml rename to test_programs/execution_success/array_sort/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/array_sort/Prover.toml b/test_programs/execution_success/array_sort/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_sort/Prover.toml rename to test_programs/execution_success/array_sort/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/array_sort/src/main.nr b/test_programs/execution_success/array_sort/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/array_sort/src/main.nr rename to test_programs/execution_success/array_sort/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/assert/Nargo.toml b/test_programs/execution_success/assert/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/assert/Nargo.toml rename to test_programs/execution_success/assert/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/assert/Prover.toml b/test_programs/execution_success/assert/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/assert/Prover.toml rename to test_programs/execution_success/assert/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/assert/src/main.nr b/test_programs/execution_success/assert/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/assert/src/main.nr rename to test_programs/execution_success/assert/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/assert_statement/Nargo.toml b/test_programs/execution_success/assert_statement/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/assert_statement/Nargo.toml rename to test_programs/execution_success/assert_statement/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/assert_statement/Prover.toml b/test_programs/execution_success/assert_statement/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/assert_statement/Prover.toml rename to test_programs/execution_success/assert_statement/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/assert_statement/src/main.nr b/test_programs/execution_success/assert_statement/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/assert_statement/src/main.nr rename to test_programs/execution_success/assert_statement/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/assign_ex/Nargo.toml b/test_programs/execution_success/assign_ex/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/assign_ex/Nargo.toml rename to test_programs/execution_success/assign_ex/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/assign_ex/Prover.toml b/test_programs/execution_success/assign_ex/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/assign_ex/Prover.toml rename to test_programs/execution_success/assign_ex/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/assign_ex/src/main.nr b/test_programs/execution_success/assign_ex/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/assign_ex/src/main.nr rename to test_programs/execution_success/assign_ex/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/bit_and/Nargo.toml b/test_programs/execution_success/bit_and/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bit_and/Nargo.toml rename to test_programs/execution_success/bit_and/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/bit_and/Prover.toml b/test_programs/execution_success/bit_and/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bit_and/Prover.toml rename to test_programs/execution_success/bit_and/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/bit_and/src/main.nr b/test_programs/execution_success/bit_and/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bit_and/src/main.nr rename to test_programs/execution_success/bit_and/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/bit_shifts_comptime/Nargo.toml b/test_programs/execution_success/bit_shifts_comptime/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bit_shifts_comptime/Nargo.toml rename to test_programs/execution_success/bit_shifts_comptime/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/bit_shifts_comptime/Prover.toml b/test_programs/execution_success/bit_shifts_comptime/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bit_shifts_comptime/Prover.toml rename to test_programs/execution_success/bit_shifts_comptime/Prover.toml diff --git a/test_programs/execution_success/bit_shifts_comptime/src/main.nr b/test_programs/execution_success/bit_shifts_comptime/src/main.nr new file mode 100644 index 0000000000..9bb1028173 --- /dev/null +++ b/test_programs/execution_success/bit_shifts_comptime/src/main.nr @@ -0,0 +1,26 @@ +fn main(x: u64) { + let two: u64 = 2; + let three: u64 = 3; + // shifts on constant values + assert(two << 2 == 8); + assert((two << 3) / 8 == two); + assert((three >> 1) == 1); + // shifts on runtime values + assert(x << 1 == 128); + assert(x >> 2 == 16); + + regression_2250(); + + //regression for 3481 + assert(x << 63 == 0); + + assert_eq((1 as u56) << (32 as u56), 0x0100000000); +} + +fn regression_2250() { + let a: u1 = 1 >> 1; + assert(a == 0); + + let b: u32 = 1 >> 32; + assert(b == 0); +} diff --git a/tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/Nargo.toml b/test_programs/execution_success/bit_shifts_runtime/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/Nargo.toml rename to test_programs/execution_success/bit_shifts_runtime/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/Prover.toml b/test_programs/execution_success/bit_shifts_runtime/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/Prover.toml rename to test_programs/execution_success/bit_shifts_runtime/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/src/main.nr b/test_programs/execution_success/bit_shifts_runtime/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/src/main.nr rename to test_programs/execution_success/bit_shifts_runtime/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/bool_not/Nargo.toml b/test_programs/execution_success/bool_not/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bool_not/Nargo.toml rename to test_programs/execution_success/bool_not/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/bool_not/Prover.toml b/test_programs/execution_success/bool_not/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bool_not/Prover.toml rename to test_programs/execution_success/bool_not/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/bool_not/src/main.nr b/test_programs/execution_success/bool_not/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bool_not/src/main.nr rename to test_programs/execution_success/bool_not/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/bool_or/Nargo.toml b/test_programs/execution_success/bool_or/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bool_or/Nargo.toml rename to test_programs/execution_success/bool_or/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/bool_or/Prover.toml b/test_programs/execution_success/bool_or/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bool_or/Prover.toml rename to test_programs/execution_success/bool_or/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/bool_or/src/main.nr b/test_programs/execution_success/bool_or/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/bool_or/src/main.nr rename to test_programs/execution_success/bool_or/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/Nargo.toml b/test_programs/execution_success/brillig_acir_as_brillig/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/Nargo.toml rename to test_programs/execution_success/brillig_acir_as_brillig/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/Prover.toml b/test_programs/execution_success/brillig_acir_as_brillig/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/Prover.toml rename to test_programs/execution_success/brillig_acir_as_brillig/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/src/main.nr b/test_programs/execution_success/brillig_acir_as_brillig/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/src/main.nr rename to test_programs/execution_success/brillig_acir_as_brillig/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_arrays/Nargo.toml b/test_programs/execution_success/brillig_arrays/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_arrays/Nargo.toml rename to test_programs/execution_success/brillig_arrays/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_arrays/Prover.toml b/test_programs/execution_success/brillig_arrays/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_arrays/Prover.toml rename to test_programs/execution_success/brillig_arrays/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_arrays/src/main.nr b/test_programs/execution_success/brillig_arrays/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_arrays/src/main.nr rename to test_programs/execution_success/brillig_arrays/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_assert/Nargo.toml b/test_programs/execution_success/brillig_assert/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_assert/Nargo.toml rename to test_programs/execution_success/brillig_assert/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_assert/Prover.toml b/test_programs/execution_success/brillig_assert/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_assert/Prover.toml rename to test_programs/execution_success/brillig_assert/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_assert/src/main.nr b/test_programs/execution_success/brillig_assert/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_assert/src/main.nr rename to test_programs/execution_success/brillig_assert/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_blake2s/Nargo.toml b/test_programs/execution_success/brillig_blake2s/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_blake2s/Nargo.toml rename to test_programs/execution_success/brillig_blake2s/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_blake2s/Prover.toml b/test_programs/execution_success/brillig_blake2s/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_blake2s/Prover.toml rename to test_programs/execution_success/brillig_blake2s/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_blake2s/src/main.nr b/test_programs/execution_success/brillig_blake2s/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_blake2s/src/main.nr rename to test_programs/execution_success/brillig_blake2s/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls/Nargo.toml b/test_programs/execution_success/brillig_calls/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_calls/Nargo.toml rename to test_programs/execution_success/brillig_calls/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls/Prover.toml b/test_programs/execution_success/brillig_calls/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_calls/Prover.toml rename to test_programs/execution_success/brillig_calls/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls/src/main.nr b/test_programs/execution_success/brillig_calls/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_calls/src/main.nr rename to test_programs/execution_success/brillig_calls/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls_array/Nargo.toml b/test_programs/execution_success/brillig_calls_array/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_calls_array/Nargo.toml rename to test_programs/execution_success/brillig_calls_array/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls_array/Prover.toml b/test_programs/execution_success/brillig_calls_array/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_calls_array/Prover.toml rename to test_programs/execution_success/brillig_calls_array/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls_array/src/main.nr b/test_programs/execution_success/brillig_calls_array/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_calls_array/src/main.nr rename to test_programs/execution_success/brillig_calls_array/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls_conditionals/Nargo.toml b/test_programs/execution_success/brillig_calls_conditionals/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_calls_conditionals/Nargo.toml rename to test_programs/execution_success/brillig_calls_conditionals/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls_conditionals/Prover.toml b/test_programs/execution_success/brillig_calls_conditionals/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_calls_conditionals/Prover.toml rename to test_programs/execution_success/brillig_calls_conditionals/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls_conditionals/src/main.nr b/test_programs/execution_success/brillig_calls_conditionals/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_calls_conditionals/src/main.nr rename to test_programs/execution_success/brillig_calls_conditionals/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_conditional/Nargo.toml b/test_programs/execution_success/brillig_conditional/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_conditional/Nargo.toml rename to test_programs/execution_success/brillig_conditional/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_conditional/Prover.toml b/test_programs/execution_success/brillig_conditional/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_conditional/Prover.toml rename to test_programs/execution_success/brillig_conditional/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_conditional/src/main.nr b/test_programs/execution_success/brillig_conditional/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_conditional/src/main.nr rename to test_programs/execution_success/brillig_conditional/src/main.nr diff --git a/test_programs/execution_success/brillig_cow/Nargo.toml b/test_programs/execution_success/brillig_cow/Nargo.toml new file mode 100644 index 0000000000..d191eb53dd --- /dev/null +++ b/test_programs/execution_success/brillig_cow/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "brillig_cow" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/brillig_cow/Prover.toml b/test_programs/execution_success/brillig_cow/Prover.toml new file mode 100644 index 0000000000..6533d218b1 --- /dev/null +++ b/test_programs/execution_success/brillig_cow/Prover.toml @@ -0,0 +1,7 @@ +original = [0, 1, 2, 3, 4] +index = 2 + +[expected_result] +original = [0, 1, 2, 3, 4] +modified_once = [0, 1, 27, 3, 4] +modified_twice = [0, 1, 27, 27, 4] diff --git a/test_programs/execution_success/brillig_cow/src/main.nr b/test_programs/execution_success/brillig_cow/src/main.nr new file mode 100644 index 0000000000..7d847e085f --- /dev/null +++ b/test_programs/execution_success/brillig_cow/src/main.nr @@ -0,0 +1,54 @@ +// Tests the copy on write optimization for arrays. We look for cases where we are modifying an array in place when we shouldn't. + +global ARRAY_SIZE = 5; + +struct ExecutionResult { + original: [Field; ARRAY_SIZE], + modified_once: [Field; ARRAY_SIZE], + modified_twice: [Field; ARRAY_SIZE], +} + +impl ExecutionResult { + fn is_equal(self, other: ExecutionResult) -> bool { + (self.original == other.original) & + (self.modified_once == other.modified_once) & + (self.modified_twice == other.modified_twice) + } +} + +fn modify_in_inlined_constrained(original: [Field; ARRAY_SIZE], index: u64) -> ExecutionResult { + let mut modified = original; + + modified[index] = 27; + + let modified_once = modified; + + modified[index+1] = 27; + + ExecutionResult { + original, + modified_once, + modified_twice: modified + } +} + +unconstrained fn modify_in_unconstrained(original: [Field; ARRAY_SIZE], index: u64) -> ExecutionResult { + let mut modified = original; + + modified[index] = 27; + + let modified_once = modified; + + modified[index+1] = 27; + + ExecutionResult { + original, + modified_once, + modified_twice: modified + } +} + +unconstrained fn main(original: [Field; ARRAY_SIZE], index: u64, expected_result: ExecutionResult) { + assert(expected_result.is_equal(modify_in_unconstrained(original, index))); + assert(expected_result.is_equal(modify_in_inlined_constrained(original, index))); +} diff --git a/tooling/nargo_cli/tests/execution_success/brillig_ecdsa/Nargo.toml b/test_programs/execution_success/brillig_ecdsa/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_ecdsa/Nargo.toml rename to test_programs/execution_success/brillig_ecdsa/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_ecdsa/Prover.toml b/test_programs/execution_success/brillig_ecdsa/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_ecdsa/Prover.toml rename to test_programs/execution_success/brillig_ecdsa/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_ecdsa/src/main.nr b/test_programs/execution_success/brillig_ecdsa/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_ecdsa/src/main.nr rename to test_programs/execution_success/brillig_ecdsa/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/Nargo.toml b/test_programs/execution_success/brillig_fns_as_values/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/Nargo.toml rename to test_programs/execution_success/brillig_fns_as_values/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/Prover.toml b/test_programs/execution_success/brillig_fns_as_values/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/Prover.toml rename to test_programs/execution_success/brillig_fns_as_values/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/src/main.nr b/test_programs/execution_success/brillig_fns_as_values/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/src/main.nr rename to test_programs/execution_success/brillig_fns_as_values/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/Nargo.toml b/test_programs/execution_success/brillig_hash_to_field/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/Nargo.toml rename to test_programs/execution_success/brillig_hash_to_field/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/Prover.toml b/test_programs/execution_success/brillig_hash_to_field/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/Prover.toml rename to test_programs/execution_success/brillig_hash_to_field/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/src/main.nr b/test_programs/execution_success/brillig_hash_to_field/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/src/main.nr rename to test_programs/execution_success/brillig_hash_to_field/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_identity_function/Nargo.toml b/test_programs/execution_success/brillig_identity_function/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_identity_function/Nargo.toml rename to test_programs/execution_success/brillig_identity_function/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_identity_function/Prover.toml b/test_programs/execution_success/brillig_identity_function/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_identity_function/Prover.toml rename to test_programs/execution_success/brillig_identity_function/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_identity_function/src/main.nr b/test_programs/execution_success/brillig_identity_function/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_identity_function/src/main.nr rename to test_programs/execution_success/brillig_identity_function/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_keccak/Nargo.toml b/test_programs/execution_success/brillig_keccak/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_keccak/Nargo.toml rename to test_programs/execution_success/brillig_keccak/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_keccak/Prover.toml b/test_programs/execution_success/brillig_keccak/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_keccak/Prover.toml rename to test_programs/execution_success/brillig_keccak/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_keccak/src/main.nr b/test_programs/execution_success/brillig_keccak/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_keccak/src/main.nr rename to test_programs/execution_success/brillig_keccak/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_loop/Nargo.toml b/test_programs/execution_success/brillig_loop/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_loop/Nargo.toml rename to test_programs/execution_success/brillig_loop/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_loop/Prover.toml b/test_programs/execution_success/brillig_loop/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_loop/Prover.toml rename to test_programs/execution_success/brillig_loop/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_loop/src/main.nr b/test_programs/execution_success/brillig_loop/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_loop/src/main.nr rename to test_programs/execution_success/brillig_loop/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/Nargo.toml b/test_programs/execution_success/brillig_nested_arrays/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/Nargo.toml rename to test_programs/execution_success/brillig_nested_arrays/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/Prover.toml b/test_programs/execution_success/brillig_nested_arrays/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/Prover.toml rename to test_programs/execution_success/brillig_nested_arrays/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/src/main.nr b/test_programs/execution_success/brillig_nested_arrays/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/src/main.nr rename to test_programs/execution_success/brillig_nested_arrays/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_nested_slices/Nargo.toml b/test_programs/execution_success/brillig_nested_slices/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_nested_slices/Nargo.toml rename to test_programs/execution_success/brillig_nested_slices/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_nested_slices/Prover.toml b/test_programs/execution_success/brillig_nested_slices/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_nested_slices/Prover.toml rename to test_programs/execution_success/brillig_nested_slices/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_nested_slices/src/main.nr b/test_programs/execution_success/brillig_nested_slices/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_nested_slices/src/main.nr rename to test_programs/execution_success/brillig_nested_slices/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_not/Nargo.toml b/test_programs/execution_success/brillig_not/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_not/Nargo.toml rename to test_programs/execution_success/brillig_not/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_not/Prover.toml b/test_programs/execution_success/brillig_not/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_not/Prover.toml rename to test_programs/execution_success/brillig_not/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_not/src/main.nr b/test_programs/execution_success/brillig_not/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_not/src/main.nr rename to test_programs/execution_success/brillig_not/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_oracle/Nargo.toml b/test_programs/execution_success/brillig_oracle/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_oracle/Nargo.toml rename to test_programs/execution_success/brillig_oracle/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_oracle/Prover.toml b/test_programs/execution_success/brillig_oracle/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_oracle/Prover.toml rename to test_programs/execution_success/brillig_oracle/Prover.toml diff --git a/test_programs/execution_success/brillig_oracle/src/main.nr b/test_programs/execution_success/brillig_oracle/src/main.nr new file mode 100644 index 0000000000..490b7b605e --- /dev/null +++ b/test_programs/execution_success/brillig_oracle/src/main.nr @@ -0,0 +1,42 @@ +use dep::std::slice; +use dep::std::test::OracleMock; + +// Tests oracle usage in brillig/unconstrained functions +fn main(x: Field) { + let size = 20; + // TODO: Add a method along the lines of `(0..size).to_array()`. + let mut mock_oracle_response = [0; 20]; + // TODO: Add an `array.reverse()` method. + let mut reversed_mock_oracle_response = [0; 20]; + for i in 0..size { + mock_oracle_response[i] = i; + reversed_mock_oracle_response[19 - i] = i; + } + + // TODO: this method of returning a slice feels hacky. + let _ = OracleMock::mock("get_number_sequence").with_params(size).returns((20, mock_oracle_response)); + let _ = OracleMock::mock("get_reverse_number_sequence").with_params(size).returns((20, reversed_mock_oracle_response)); + + get_number_sequence_wrapper(size); +} + +// Define oracle functions which we have mocked above +#[oracle(get_number_sequence)] +unconstrained fn get_number_sequence(_size: Field) -> [Field] {} + +#[oracle(get_reverse_number_sequence)] +unconstrained fn get_reverse_number_sequence(_size: Field) -> [Field] {} + +unconstrained fn get_number_sequence_wrapper(size: Field) { + let slice = get_number_sequence(size); + for i in 0..20 as u32 { + assert(slice[i] == i as Field); + } + + let reversed_slice = get_reverse_number_sequence(size); + // Regression test that we have not overwritten memory + for i in 0..20 as u32 { + assert(slice[i] == reversed_slice[19 - i]); + } +} + diff --git a/tooling/nargo_cli/tests/execution_success/brillig_pedersen/Nargo.toml b/test_programs/execution_success/brillig_pedersen/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_pedersen/Nargo.toml rename to test_programs/execution_success/brillig_pedersen/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_pedersen/Prover.toml b/test_programs/execution_success/brillig_pedersen/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_pedersen/Prover.toml rename to test_programs/execution_success/brillig_pedersen/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_pedersen/src/main.nr b/test_programs/execution_success/brillig_pedersen/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_pedersen/src/main.nr rename to test_programs/execution_success/brillig_pedersen/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_recursion/Nargo.toml b/test_programs/execution_success/brillig_recursion/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_recursion/Nargo.toml rename to test_programs/execution_success/brillig_recursion/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_recursion/Prover.toml b/test_programs/execution_success/brillig_recursion/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_recursion/Prover.toml rename to test_programs/execution_success/brillig_recursion/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_recursion/src/main.nr b/test_programs/execution_success/brillig_recursion/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_recursion/src/main.nr rename to test_programs/execution_success/brillig_recursion/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_references/Nargo.toml b/test_programs/execution_success/brillig_references/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_references/Nargo.toml rename to test_programs/execution_success/brillig_references/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_references/Prover.toml b/test_programs/execution_success/brillig_references/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_references/Prover.toml rename to test_programs/execution_success/brillig_references/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_references/src/main.nr b/test_programs/execution_success/brillig_references/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_references/src/main.nr rename to test_programs/execution_success/brillig_references/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_scalar_mul/Nargo.toml b/test_programs/execution_success/brillig_scalar_mul/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_scalar_mul/Nargo.toml rename to test_programs/execution_success/brillig_scalar_mul/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_scalar_mul/Prover.toml b/test_programs/execution_success/brillig_scalar_mul/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_scalar_mul/Prover.toml rename to test_programs/execution_success/brillig_scalar_mul/Prover.toml diff --git a/test_programs/execution_success/brillig_scalar_mul/src/main.nr b/test_programs/execution_success/brillig_scalar_mul/src/main.nr new file mode 100644 index 0000000000..ab2f79eb81 --- /dev/null +++ b/test_programs/execution_success/brillig_scalar_mul/src/main.nr @@ -0,0 +1,23 @@ +use dep::std; + +unconstrained fn main( + a: Field, + a_pub_x: pub Field, + a_pub_y: pub Field, + b: Field, + b_pub_x: pub Field, + b_pub_y: pub Field +) { + let mut priv_key = a; + let mut pub_x: Field = a_pub_x; + let mut pub_y: Field = a_pub_y; + if a != 1 { + // Change `a` in Prover.toml to test input `b` + priv_key = b; + pub_x = b_pub_x; + pub_y = b_pub_y; + } + let res = std::scalar_mul::fixed_base_embedded_curve(priv_key, 0); + assert(res[0] == pub_x); + assert(res[1] == pub_y); +} diff --git a/tooling/nargo_cli/tests/execution_success/brillig_schnorr/Nargo.toml b/test_programs/execution_success/brillig_schnorr/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_schnorr/Nargo.toml rename to test_programs/execution_success/brillig_schnorr/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_schnorr/Prover.toml b/test_programs/execution_success/brillig_schnorr/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_schnorr/Prover.toml rename to test_programs/execution_success/brillig_schnorr/Prover.toml diff --git a/test_programs/execution_success/brillig_schnorr/src/main.nr b/test_programs/execution_success/brillig_schnorr/src/main.nr new file mode 100644 index 0000000000..4cc79ae7e0 --- /dev/null +++ b/test_programs/execution_success/brillig_schnorr/src/main.nr @@ -0,0 +1,25 @@ +use dep::std; +// Note: If main has any unsized types, then the verifier will never be able +// to figure out the circuit instance +unconstrained fn main( + message: [u8; 10], + message_field: Field, + pub_key_x: Field, + pub_key_y: Field, + signature: [u8; 64] +) { + // Regression for issue #2421 + // We want to make sure that we can accurately verify a signature whose message is a slice vs. an array + let message_field_bytes = message_field.to_be_bytes(10); + for i in 0..10 { + assert(message[i] == message_field_bytes[i]); + } + // Is there ever a situation where someone would want + // to ensure that a signature was invalid? + // Check that passing a slice as the message is valid + let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message_field_bytes); + assert(valid_signature); + // Check that passing an array as the message is valid + let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message); + assert(valid_signature); +} diff --git a/test_programs/execution_success/brillig_set_slice_of_slice/Nargo.toml b/test_programs/execution_success/brillig_set_slice_of_slice/Nargo.toml new file mode 100644 index 0000000000..071254266f --- /dev/null +++ b/test_programs/execution_success/brillig_set_slice_of_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "brillig_set_slice_of_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.19.4" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/brillig_set_slice_of_slice/src/main.nr b/test_programs/execution_success/brillig_set_slice_of_slice/src/main.nr new file mode 100644 index 0000000000..c0e9c7d172 --- /dev/null +++ b/test_programs/execution_success/brillig_set_slice_of_slice/src/main.nr @@ -0,0 +1,51 @@ +struct Property +{ + key : [u8], + value : [u8], +} + +struct JSON +{ + doc : [Property] +} + +unconstrained fn slice_eq(self: [u8], other: [u8]) -> bool { + let mut equal = true; + for i in 0..self.len() { + if self[i] != other[i] { + equal = false; + } + } + equal +} + +// This test acts a regression for issue #3476 +unconstrained fn main() { + let mut json = JSON { doc: [] }; + let mut prop = Property { key: [], value:[] }; + + let other_prop = Property { key: [0, 1, 2], value:[10] }; + json.doc = json.doc.push_back(other_prop); + + for i in 0..3 { + prop.key = prop.key.push_back(i as u8); + } + prop.value = prop.value.push_back(5); + + // add property to json or replace existing + let len : Field = json.doc.len(); + let mut found = false; + for i in 0..len + { + if (!found) + { + if (slice_eq(prop.key, json.doc[i].key)) + { + json.doc[i].value = prop.value; + found = true; + } + } + } + assert(found == true); + assert(json.doc[0].value[0] == 5); +} \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/brillig_sha256/Nargo.toml b/test_programs/execution_success/brillig_sha256/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_sha256/Nargo.toml rename to test_programs/execution_success/brillig_sha256/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_sha256/Prover.toml b/test_programs/execution_success/brillig_sha256/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_sha256/Prover.toml rename to test_programs/execution_success/brillig_sha256/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_sha256/src/main.nr b/test_programs/execution_success/brillig_sha256/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_sha256/src/main.nr rename to test_programs/execution_success/brillig_sha256/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_slices/Nargo.toml b/test_programs/execution_success/brillig_slices/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_slices/Nargo.toml rename to test_programs/execution_success/brillig_slices/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_slices/Prover.toml b/test_programs/execution_success/brillig_slices/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_slices/Prover.toml rename to test_programs/execution_success/brillig_slices/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_slices/src/main.nr b/test_programs/execution_success/brillig_slices/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_slices/src/main.nr rename to test_programs/execution_success/brillig_slices/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/Nargo.toml b/test_programs/execution_success/brillig_to_be_bytes/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/Nargo.toml rename to test_programs/execution_success/brillig_to_be_bytes/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/Prover.toml b/test_programs/execution_success/brillig_to_be_bytes/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/Prover.toml rename to test_programs/execution_success/brillig_to_be_bytes/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/src/main.nr b/test_programs/execution_success/brillig_to_be_bytes/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/src/main.nr rename to test_programs/execution_success/brillig_to_be_bytes/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/Nargo.toml b/test_programs/execution_success/brillig_to_bytes_integration/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/Nargo.toml rename to test_programs/execution_success/brillig_to_bytes_integration/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/Prover.toml b/test_programs/execution_success/brillig_to_bytes_integration/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/Prover.toml rename to test_programs/execution_success/brillig_to_bytes_integration/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/src/main.nr b/test_programs/execution_success/brillig_to_bytes_integration/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/src/main.nr rename to test_programs/execution_success/brillig_to_bytes_integration/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/Nargo.toml b/test_programs/execution_success/brillig_to_le_bytes/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/Nargo.toml rename to test_programs/execution_success/brillig_to_le_bytes/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/Prover.toml b/test_programs/execution_success/brillig_to_le_bytes/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/Prover.toml rename to test_programs/execution_success/brillig_to_le_bytes/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/src/main.nr b/test_programs/execution_success/brillig_to_le_bytes/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/src/main.nr rename to test_programs/execution_success/brillig_to_le_bytes/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_top_level/Nargo.toml b/test_programs/execution_success/brillig_top_level/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_top_level/Nargo.toml rename to test_programs/execution_success/brillig_top_level/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_top_level/Prover.toml b/test_programs/execution_success/brillig_top_level/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_top_level/Prover.toml rename to test_programs/execution_success/brillig_top_level/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_top_level/src/main.nr b/test_programs/execution_success/brillig_top_level/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_top_level/src/main.nr rename to test_programs/execution_success/brillig_top_level/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/brillig_unitialised_arrays/Nargo.toml b/test_programs/execution_success/brillig_unitialised_arrays/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_unitialised_arrays/Nargo.toml rename to test_programs/execution_success/brillig_unitialised_arrays/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_unitialised_arrays/Prover.toml b/test_programs/execution_success/brillig_unitialised_arrays/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_unitialised_arrays/Prover.toml rename to test_programs/execution_success/brillig_unitialised_arrays/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/brillig_unitialised_arrays/src/main.nr b/test_programs/execution_success/brillig_unitialised_arrays/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/brillig_unitialised_arrays/src/main.nr rename to test_programs/execution_success/brillig_unitialised_arrays/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/cast_bool/Nargo.toml b/test_programs/execution_success/cast_bool/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/cast_bool/Nargo.toml rename to test_programs/execution_success/cast_bool/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/cast_bool/Prover.toml b/test_programs/execution_success/cast_bool/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/cast_bool/Prover.toml rename to test_programs/execution_success/cast_bool/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/cast_bool/src/main.nr b/test_programs/execution_success/cast_bool/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/cast_bool/src/main.nr rename to test_programs/execution_success/cast_bool/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/closures_mut_ref/Nargo.toml b/test_programs/execution_success/closures_mut_ref/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/closures_mut_ref/Nargo.toml rename to test_programs/execution_success/closures_mut_ref/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/closures_mut_ref/Prover.toml b/test_programs/execution_success/closures_mut_ref/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/closures_mut_ref/Prover.toml rename to test_programs/execution_success/closures_mut_ref/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/closures_mut_ref/src/main.nr b/test_programs/execution_success/closures_mut_ref/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/closures_mut_ref/src/main.nr rename to test_programs/execution_success/closures_mut_ref/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/conditional_1/Nargo.toml b/test_programs/execution_success/conditional_1/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_1/Nargo.toml rename to test_programs/execution_success/conditional_1/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/conditional_1/Prover.toml b/test_programs/execution_success/conditional_1/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_1/Prover.toml rename to test_programs/execution_success/conditional_1/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/conditional_1/src/main.nr b/test_programs/execution_success/conditional_1/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_1/src/main.nr rename to test_programs/execution_success/conditional_1/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/conditional_2/Nargo.toml b/test_programs/execution_success/conditional_2/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_2/Nargo.toml rename to test_programs/execution_success/conditional_2/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/conditional_2/Prover.toml b/test_programs/execution_success/conditional_2/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_2/Prover.toml rename to test_programs/execution_success/conditional_2/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/conditional_2/src/main.nr b/test_programs/execution_success/conditional_2/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_2/src/main.nr rename to test_programs/execution_success/conditional_2/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_421/Nargo.toml b/test_programs/execution_success/conditional_regression_421/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_regression_421/Nargo.toml rename to test_programs/execution_success/conditional_regression_421/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_421/Prover.toml b/test_programs/execution_success/conditional_regression_421/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_regression_421/Prover.toml rename to test_programs/execution_success/conditional_regression_421/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_421/src/main.nr b/test_programs/execution_success/conditional_regression_421/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_regression_421/src/main.nr rename to test_programs/execution_success/conditional_regression_421/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_661/Nargo.toml b/test_programs/execution_success/conditional_regression_661/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_regression_661/Nargo.toml rename to test_programs/execution_success/conditional_regression_661/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_661/Prover.toml b/test_programs/execution_success/conditional_regression_661/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_regression_661/Prover.toml rename to test_programs/execution_success/conditional_regression_661/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_661/src/main.nr b/test_programs/execution_success/conditional_regression_661/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_regression_661/src/main.nr rename to test_programs/execution_success/conditional_regression_661/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/Nargo.toml b/test_programs/execution_success/conditional_regression_short_circuit/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/Nargo.toml rename to test_programs/execution_success/conditional_regression_short_circuit/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/Prover.toml b/test_programs/execution_success/conditional_regression_short_circuit/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/Prover.toml rename to test_programs/execution_success/conditional_regression_short_circuit/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/src/main.nr b/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/src/main.nr rename to test_programs/execution_success/conditional_regression_short_circuit/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/Nargo.toml b/test_programs/execution_success/conditional_regression_underflow/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/Nargo.toml rename to test_programs/execution_success/conditional_regression_underflow/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/Prover.toml b/test_programs/execution_success/conditional_regression_underflow/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/Prover.toml rename to test_programs/execution_success/conditional_regression_underflow/Prover.toml diff --git a/test_programs/execution_success/conditional_regression_underflow/src/main.nr b/test_programs/execution_success/conditional_regression_underflow/src/main.nr new file mode 100644 index 0000000000..a101af3250 --- /dev/null +++ b/test_programs/execution_success/conditional_regression_underflow/src/main.nr @@ -0,0 +1,15 @@ +// Regression test for https://github.com/noir-lang/noir/issues/3493 +fn main(x: u4) { + if x == 10 { + x + 15; + } + if x == 9 { + x << 3; + } + if x == 8 { + x * 3; + } + if x == 7 { + x - 8; + } +} diff --git a/tooling/nargo_cli/tests/execution_success/custom_entry/Nargo.toml b/test_programs/execution_success/custom_entry/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/custom_entry/Nargo.toml rename to test_programs/execution_success/custom_entry/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/custom_entry/Prover.toml b/test_programs/execution_success/custom_entry/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/custom_entry/Prover.toml rename to test_programs/execution_success/custom_entry/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/custom_entry/src/foobarbaz.nr b/test_programs/execution_success/custom_entry/src/foobarbaz.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/custom_entry/src/foobarbaz.nr rename to test_programs/execution_success/custom_entry/src/foobarbaz.nr diff --git a/test_programs/execution_success/databus/Nargo.toml b/test_programs/execution_success/databus/Nargo.toml new file mode 100644 index 0000000000..72360f7aef --- /dev/null +++ b/test_programs/execution_success/databus/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "databus" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/databus/Prover.toml b/test_programs/execution_success/databus/Prover.toml new file mode 100644 index 0000000000..2d034508dd --- /dev/null +++ b/test_programs/execution_success/databus/Prover.toml @@ -0,0 +1,3 @@ +x = "3" +y = "4" +z = [1,2,3,4] diff --git a/test_programs/execution_success/databus/src/main.nr b/test_programs/execution_success/databus/src/main.nr new file mode 100644 index 0000000000..631331ef2d --- /dev/null +++ b/test_programs/execution_success/databus/src/main.nr @@ -0,0 +1,10 @@ +// Test unsafe integer multiplication with overflow: 12^8 = 429 981 696 +// The circuit should handle properly the growth of the bit size +use dep::std; + +fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { + +let a = z[x]; + a+y + +} diff --git a/tooling/nargo_cli/tests/execution_success/debug_logs/Nargo.toml b/test_programs/execution_success/debug_logs/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/debug_logs/Nargo.toml rename to test_programs/execution_success/debug_logs/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/debug_logs/Prover.toml b/test_programs/execution_success/debug_logs/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/debug_logs/Prover.toml rename to test_programs/execution_success/debug_logs/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/debug_logs/src/main.nr b/test_programs/execution_success/debug_logs/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/debug_logs/src/main.nr rename to test_programs/execution_success/debug_logs/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/diamond_deps_0/Nargo.toml b/test_programs/execution_success/diamond_deps_0/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/diamond_deps_0/Nargo.toml rename to test_programs/execution_success/diamond_deps_0/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/diamond_deps_0/Prover.toml b/test_programs/execution_success/diamond_deps_0/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/diamond_deps_0/Prover.toml rename to test_programs/execution_success/diamond_deps_0/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/diamond_deps_0/src/main.nr b/test_programs/execution_success/diamond_deps_0/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/diamond_deps_0/src/main.nr rename to test_programs/execution_success/diamond_deps_0/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/distinct_keyword/Nargo.toml b/test_programs/execution_success/distinct_keyword/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/distinct_keyword/Nargo.toml rename to test_programs/execution_success/distinct_keyword/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/distinct_keyword/Prover.toml b/test_programs/execution_success/distinct_keyword/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/distinct_keyword/Prover.toml rename to test_programs/execution_success/distinct_keyword/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/distinct_keyword/src/main.nr b/test_programs/execution_success/distinct_keyword/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/distinct_keyword/src/main.nr rename to test_programs/execution_success/distinct_keyword/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/double_verify_proof/Nargo.toml b/test_programs/execution_success/double_verify_proof/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/double_verify_proof/Nargo.toml rename to test_programs/execution_success/double_verify_proof/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/double_verify_proof/Prover.toml b/test_programs/execution_success/double_verify_proof/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/double_verify_proof/Prover.toml rename to test_programs/execution_success/double_verify_proof/Prover.toml diff --git a/test_programs/execution_success/double_verify_proof/src/main.nr b/test_programs/execution_success/double_verify_proof/src/main.nr new file mode 100644 index 0000000000..98cd534266 --- /dev/null +++ b/test_programs/execution_success/double_verify_proof/src/main.nr @@ -0,0 +1,32 @@ +use dep::std; + +fn main( + verification_key: [Field; 114], + proof: [Field; 94], + public_inputs: [Field; 1], + key_hash: Field, + input_aggregation_object: [Field; 16], + proof_b: [Field; 94] +) -> pub [Field; 16] { + let output_aggregation_object_a = std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash, + input_aggregation_object + ); + + let output_aggregation_object = std::verify_proof( + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), + key_hash, + output_aggregation_object_a + ); + + let mut output = [0; 16]; + for i in 0..16 { + output[i] = output_aggregation_object[i]; + } + output +} diff --git a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/Nargo.toml b/test_programs/execution_success/ecdsa_secp256k1/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/Nargo.toml rename to test_programs/execution_success/ecdsa_secp256k1/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/Prover.toml b/test_programs/execution_success/ecdsa_secp256k1/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/Prover.toml rename to test_programs/execution_success/ecdsa_secp256k1/Prover.toml diff --git a/test_programs/execution_success/ecdsa_secp256k1/src/main.nr b/test_programs/execution_success/ecdsa_secp256k1/src/main.nr new file mode 100644 index 0000000000..2f410755f7 --- /dev/null +++ b/test_programs/execution_success/ecdsa_secp256k1/src/main.nr @@ -0,0 +1,16 @@ +use dep::std; + +fn main( + message: [u8;38], + hashed_message: [u8;32], + pub_key_x: [u8;32], + pub_key_y: [u8;32], + signature: [u8;64] +) { + // Hash the message, since secp256k1 expects a hashed_message + let expected = std::hash::sha256(message); + assert(hashed_message == expected); + + let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} diff --git a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/Nargo.toml b/test_programs/execution_success/ecdsa_secp256r1/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/Nargo.toml rename to test_programs/execution_success/ecdsa_secp256r1/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/Prover.toml b/test_programs/execution_success/ecdsa_secp256r1/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/Prover.toml rename to test_programs/execution_success/ecdsa_secp256r1/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/src/main.nr b/test_programs/execution_success/ecdsa_secp256r1/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/src/main.nr rename to test_programs/execution_success/ecdsa_secp256r1/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/eddsa/Nargo.toml b/test_programs/execution_success/eddsa/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/eddsa/Nargo.toml rename to test_programs/execution_success/eddsa/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/eddsa/Prover.toml b/test_programs/execution_success/eddsa/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/eddsa/Prover.toml rename to test_programs/execution_success/eddsa/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/eddsa/src/main.nr b/test_programs/execution_success/eddsa/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/eddsa/src/main.nr rename to test_programs/execution_success/eddsa/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/field_attribute/Nargo.toml b/test_programs/execution_success/field_attribute/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/field_attribute/Nargo.toml rename to test_programs/execution_success/field_attribute/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/field_attribute/Prover.toml b/test_programs/execution_success/field_attribute/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/field_attribute/Prover.toml rename to test_programs/execution_success/field_attribute/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/field_attribute/src/main.nr b/test_programs/execution_success/field_attribute/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/field_attribute/src/main.nr rename to test_programs/execution_success/field_attribute/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/generics/Nargo.toml b/test_programs/execution_success/generics/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/generics/Nargo.toml rename to test_programs/execution_success/generics/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/generics/Prover.toml b/test_programs/execution_success/generics/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/generics/Prover.toml rename to test_programs/execution_success/generics/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/generics/src/main.nr b/test_programs/execution_success/generics/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/generics/src/main.nr rename to test_programs/execution_success/generics/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/global_consts/Nargo.toml b/test_programs/execution_success/global_consts/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/global_consts/Nargo.toml rename to test_programs/execution_success/global_consts/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/global_consts/Prover.toml b/test_programs/execution_success/global_consts/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/global_consts/Prover.toml rename to test_programs/execution_success/global_consts/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/global_consts/src/baz.nr b/test_programs/execution_success/global_consts/src/baz.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/global_consts/src/baz.nr rename to test_programs/execution_success/global_consts/src/baz.nr diff --git a/tooling/nargo_cli/tests/execution_success/global_consts/src/foo.nr b/test_programs/execution_success/global_consts/src/foo.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/global_consts/src/foo.nr rename to test_programs/execution_success/global_consts/src/foo.nr diff --git a/tooling/nargo_cli/tests/execution_success/global_consts/src/foo/bar.nr b/test_programs/execution_success/global_consts/src/foo/bar.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/global_consts/src/foo/bar.nr rename to test_programs/execution_success/global_consts/src/foo/bar.nr diff --git a/tooling/nargo_cli/tests/execution_success/global_consts/src/main.nr b/test_programs/execution_success/global_consts/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/global_consts/src/main.nr rename to test_programs/execution_success/global_consts/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/hash_to_field/Nargo.toml b/test_programs/execution_success/hash_to_field/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/hash_to_field/Nargo.toml rename to test_programs/execution_success/hash_to_field/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/hash_to_field/Prover.toml b/test_programs/execution_success/hash_to_field/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/hash_to_field/Prover.toml rename to test_programs/execution_success/hash_to_field/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/hash_to_field/src/main.nr b/test_programs/execution_success/hash_to_field/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/hash_to_field/src/main.nr rename to test_programs/execution_success/hash_to_field/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/higher_order_functions/Nargo.toml b/test_programs/execution_success/higher_order_functions/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/higher_order_functions/Nargo.toml rename to test_programs/execution_success/higher_order_functions/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/higher_order_functions/Prover.toml b/test_programs/execution_success/higher_order_functions/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/higher_order_functions/Prover.toml rename to test_programs/execution_success/higher_order_functions/Prover.toml diff --git a/test_programs/execution_success/higher_order_functions/src/main.nr b/test_programs/execution_success/higher_order_functions/src/main.nr new file mode 100644 index 0000000000..6583f961d5 --- /dev/null +++ b/test_programs/execution_success/higher_order_functions/src/main.nr @@ -0,0 +1,99 @@ +fn main(w: Field) -> pub Field { + let f = if 3 * 7 > 200 as u32 { foo } else { bar }; + assert(f()[1] == 2); + // Lambdas: + assert(twice(|x| x * 2, 5) == 20); + assert((|x, y| x + y + 1)(2, 3) == 6); + // nested lambdas + assert( + (|a, b| { + a + (|c| c + 2)(b) + })(0, 1) + == 3 + ); + // Closures: + let a = 42; + let g = || a; + assert(g() == 42); + // When you copy mutable variables, + // the capture of the copies shouldn't change: + let mut x = 2; + x = x + 1; + let z = x; + // Add extra mutations to ensure we can mutate x without the + // captured z changing. + x = x + 1; + assert((|y| y + z)(1) == 4); + // When you capture mutable variables, + // again, the captured variable doesn't change: + let closure_capturing_mutable = (|y| y + x); + assert(closure_capturing_mutable(1) == 5); + x += 1; + assert(closure_capturing_mutable(1) == 5); + + regression_2154(); + + let ret = twice(add1, 3); + + test_array_functions(); + w + ret +} +/// Test the array functions in std::array +fn test_array_functions() { + let two = 2; // giving this a name, to ensure that the Option functions work with closures + let myarray: [i32; 3] = [1, 2, 3]; + assert(myarray.any(|n| n > 2)); + assert(myarray.any(|n| n > two)); + + let evens: [i32; 3] = myarray.map(|n| n * two); // [2, 4, 6] + assert(evens.all(|n| n > 1)); + assert(evens.all(|n| n >= two)); + + assert(evens.fold(0, |a, b| a + b) == 12); + assert(evens.fold(0, |a, b| a + b + two) == 18); + assert(evens.reduce(|a, b| a + b) == 12); + assert(evens.reduce(|a, b| a + b + two) == 16); + // TODO: is this a sort_via issue with the new backend, + // or something more general? + // + // currently it fails only with `--experimental-ssa` with + // "not yet implemented: Cast into signed" + // but it worked with the original ssa backend + // (before dropping it) + // + // opened #2121 for it + // https://github.com/noir-lang/noir/issues/2121 + // let descending = myarray.sort_via(|a, b| a > b); + // assert(descending == [3, 2, 1]); + assert(evens.map(|n| n / 2) == myarray); + assert(evens.map(|n| n / two) == myarray); +} + +fn foo() -> [u32; 2] { + [1, 3] +} + +fn bar() -> [u32; 2] { + [3, 2] +} + +fn add1(x: Field) -> Field { + x + 1 +} + +fn twice(f: fn(Field) -> Field, x: Field) -> Field { + f(f(x)) +} +// Fixing an ICE, where rewriting the closures +// during monomorphization didn't correspond +// to an internal `if` type +// found by @jfecher: +// https://github.com/noir-lang/noir/pull/1959#issuecomment-1658992989 +// issue https://github.com/noir-lang/noir/issues/2154 +fn regression_2154() { + let x: u32 = 32; + + let closure_if_else = if x > 2 { || x } else { || x + 2342 }; + + assert(closure_if_else() == 32); +} diff --git a/tooling/nargo_cli/tests/execution_success/if_else_chain/Nargo.toml b/test_programs/execution_success/if_else_chain/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/if_else_chain/Nargo.toml rename to test_programs/execution_success/if_else_chain/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/if_else_chain/Prover.toml b/test_programs/execution_success/if_else_chain/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/if_else_chain/Prover.toml rename to test_programs/execution_success/if_else_chain/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/if_else_chain/src/main.nr b/test_programs/execution_success/if_else_chain/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/if_else_chain/src/main.nr rename to test_programs/execution_success/if_else_chain/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/import/Nargo.toml b/test_programs/execution_success/import/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/import/Nargo.toml rename to test_programs/execution_success/import/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/import/Prover.toml b/test_programs/execution_success/import/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/import/Prover.toml rename to test_programs/execution_success/import/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/import/src/import.nr b/test_programs/execution_success/import/src/import.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/import/src/import.nr rename to test_programs/execution_success/import/src/import.nr diff --git a/tooling/nargo_cli/tests/execution_success/import/src/main.nr b/test_programs/execution_success/import/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/import/src/main.nr rename to test_programs/execution_success/import/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/integer_array_indexing/Nargo.toml b/test_programs/execution_success/integer_array_indexing/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/integer_array_indexing/Nargo.toml rename to test_programs/execution_success/integer_array_indexing/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/integer_array_indexing/Prover.toml b/test_programs/execution_success/integer_array_indexing/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/integer_array_indexing/Prover.toml rename to test_programs/execution_success/integer_array_indexing/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/integer_array_indexing/src/main.nr b/test_programs/execution_success/integer_array_indexing/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/integer_array_indexing/src/main.nr rename to test_programs/execution_success/integer_array_indexing/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/keccak256/Nargo.toml b/test_programs/execution_success/keccak256/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/keccak256/Nargo.toml rename to test_programs/execution_success/keccak256/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/keccak256/Prover.toml b/test_programs/execution_success/keccak256/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/keccak256/Prover.toml rename to test_programs/execution_success/keccak256/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/keccak256/src/main.nr b/test_programs/execution_success/keccak256/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/keccak256/src/main.nr rename to test_programs/execution_success/keccak256/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/main_bool_arg/Nargo.toml b/test_programs/execution_success/main_bool_arg/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/main_bool_arg/Nargo.toml rename to test_programs/execution_success/main_bool_arg/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/main_bool_arg/Prover.toml b/test_programs/execution_success/main_bool_arg/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/main_bool_arg/Prover.toml rename to test_programs/execution_success/main_bool_arg/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/main_bool_arg/src/main.nr b/test_programs/execution_success/main_bool_arg/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/main_bool_arg/src/main.nr rename to test_programs/execution_success/main_bool_arg/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/merkle_insert/Nargo.toml b/test_programs/execution_success/merkle_insert/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/merkle_insert/Nargo.toml rename to test_programs/execution_success/merkle_insert/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/merkle_insert/Prover.toml b/test_programs/execution_success/merkle_insert/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/merkle_insert/Prover.toml rename to test_programs/execution_success/merkle_insert/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/merkle_insert/src/main.nr b/test_programs/execution_success/merkle_insert/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/merkle_insert/src/main.nr rename to test_programs/execution_success/merkle_insert/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/mock_oracle/Nargo.toml b/test_programs/execution_success/mock_oracle/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/mock_oracle/Nargo.toml rename to test_programs/execution_success/mock_oracle/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/mock_oracle/Prover.toml b/test_programs/execution_success/mock_oracle/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/mock_oracle/Prover.toml rename to test_programs/execution_success/mock_oracle/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/mock_oracle/src/main.nr b/test_programs/execution_success/mock_oracle/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/mock_oracle/src/main.nr rename to test_programs/execution_success/mock_oracle/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/modules/Nargo.toml b/test_programs/execution_success/modules/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/modules/Nargo.toml rename to test_programs/execution_success/modules/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/modules/Prover.toml b/test_programs/execution_success/modules/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/modules/Prover.toml rename to test_programs/execution_success/modules/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/modules/src/foo.nr b/test_programs/execution_success/modules/src/foo.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/modules/src/foo.nr rename to test_programs/execution_success/modules/src/foo.nr diff --git a/tooling/nargo_cli/tests/execution_success/modules/src/main.nr b/test_programs/execution_success/modules/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/modules/src/main.nr rename to test_programs/execution_success/modules/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/modules_more/Nargo.toml b/test_programs/execution_success/modules_more/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/modules_more/Nargo.toml rename to test_programs/execution_success/modules_more/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/modules_more/Prover.toml b/test_programs/execution_success/modules_more/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/modules_more/Prover.toml rename to test_programs/execution_success/modules_more/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/modules_more/src/foo.nr b/test_programs/execution_success/modules_more/src/foo.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/modules_more/src/foo.nr rename to test_programs/execution_success/modules_more/src/foo.nr diff --git a/tooling/nargo_cli/tests/execution_success/modules_more/src/foo/bar.nr b/test_programs/execution_success/modules_more/src/foo/bar.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/modules_more/src/foo/bar.nr rename to test_programs/execution_success/modules_more/src/foo/bar.nr diff --git a/tooling/nargo_cli/tests/execution_success/modules_more/src/main.nr b/test_programs/execution_success/modules_more/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/modules_more/src/main.nr rename to test_programs/execution_success/modules_more/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/modulus/Nargo.toml b/test_programs/execution_success/modulus/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/modulus/Nargo.toml rename to test_programs/execution_success/modulus/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/modulus/Prover.toml b/test_programs/execution_success/modulus/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/modulus/Prover.toml rename to test_programs/execution_success/modulus/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/modulus/src/main.nr b/test_programs/execution_success/modulus/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/modulus/src/main.nr rename to test_programs/execution_success/modulus/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/Nargo.toml b/test_programs/execution_success/nested_array_dynamic/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/nested_array_dynamic/Nargo.toml rename to test_programs/execution_success/nested_array_dynamic/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/Prover.toml b/test_programs/execution_success/nested_array_dynamic/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/nested_array_dynamic/Prover.toml rename to test_programs/execution_success/nested_array_dynamic/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/src/main.nr b/test_programs/execution_success/nested_array_dynamic/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/nested_array_dynamic/src/main.nr rename to test_programs/execution_success/nested_array_dynamic/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/Nargo.toml b/test_programs/execution_success/nested_arrays_from_brillig/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/Nargo.toml rename to test_programs/execution_success/nested_arrays_from_brillig/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/Prover.toml b/test_programs/execution_success/nested_arrays_from_brillig/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/Prover.toml rename to test_programs/execution_success/nested_arrays_from_brillig/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/src/main.nr b/test_programs/execution_success/nested_arrays_from_brillig/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/src/main.nr rename to test_programs/execution_success/nested_arrays_from_brillig/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/Nargo.toml b/test_programs/execution_success/nested_slice_dynamic/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/Nargo.toml rename to test_programs/execution_success/nested_slice_dynamic/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/Prover.toml b/test_programs/execution_success/nested_slice_dynamic/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/Prover.toml rename to test_programs/execution_success/nested_slice_dynamic/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/src/main.nr b/test_programs/execution_success/nested_slice_dynamic/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/src/main.nr rename to test_programs/execution_success/nested_slice_dynamic/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/pedersen_check/Nargo.toml b/test_programs/execution_success/pedersen_check/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/pedersen_check/Nargo.toml rename to test_programs/execution_success/pedersen_check/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/pedersen_check/Prover.toml b/test_programs/execution_success/pedersen_check/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/pedersen_check/Prover.toml rename to test_programs/execution_success/pedersen_check/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/pedersen_check/src/main.nr b/test_programs/execution_success/pedersen_check/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/pedersen_check/src/main.nr rename to test_programs/execution_success/pedersen_check/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/poseidon_bn254_hash/Nargo.toml b/test_programs/execution_success/poseidon_bn254_hash/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/poseidon_bn254_hash/Nargo.toml rename to test_programs/execution_success/poseidon_bn254_hash/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/poseidon_bn254_hash/Prover.toml b/test_programs/execution_success/poseidon_bn254_hash/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/poseidon_bn254_hash/Prover.toml rename to test_programs/execution_success/poseidon_bn254_hash/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/poseidon_bn254_hash/src/main.nr b/test_programs/execution_success/poseidon_bn254_hash/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/poseidon_bn254_hash/src/main.nr rename to test_programs/execution_success/poseidon_bn254_hash/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/Nargo.toml b/test_programs/execution_success/poseidonsponge_x5_254/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/Nargo.toml rename to test_programs/execution_success/poseidonsponge_x5_254/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/Prover.toml b/test_programs/execution_success/poseidonsponge_x5_254/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/Prover.toml rename to test_programs/execution_success/poseidonsponge_x5_254/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/src/main.nr b/test_programs/execution_success/poseidonsponge_x5_254/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/src/main.nr rename to test_programs/execution_success/poseidonsponge_x5_254/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/pred_eq/Nargo.toml b/test_programs/execution_success/pred_eq/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/pred_eq/Nargo.toml rename to test_programs/execution_success/pred_eq/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/pred_eq/Prover.toml b/test_programs/execution_success/pred_eq/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/pred_eq/Prover.toml rename to test_programs/execution_success/pred_eq/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/pred_eq/src/main.nr b/test_programs/execution_success/pred_eq/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/pred_eq/src/main.nr rename to test_programs/execution_success/pred_eq/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/references/Nargo.toml b/test_programs/execution_success/references/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/references/Nargo.toml rename to test_programs/execution_success/references/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/references/Prover.toml b/test_programs/execution_success/references/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/references/Prover.toml rename to test_programs/execution_success/references/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/references/src/main.nr b/test_programs/execution_success/references/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/references/src/main.nr rename to test_programs/execution_success/references/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/regression/Nargo.toml b/test_programs/execution_success/regression/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/regression/Nargo.toml rename to test_programs/execution_success/regression/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/regression/Prover.toml b/test_programs/execution_success/regression/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/regression/Prover.toml rename to test_programs/execution_success/regression/Prover.toml diff --git a/test_programs/execution_success/regression/src/main.nr b/test_programs/execution_success/regression/src/main.nr new file mode 100644 index 0000000000..08112d4c61 --- /dev/null +++ b/test_programs/execution_success/regression/src/main.nr @@ -0,0 +1,109 @@ +global NIBBLE_LENGTH: Field = 16; + +fn compact_decode(input: [u8; N], length: Field) -> ([u4; NIBBLE_LENGTH], Field) { + assert(2 * input.len() as u64 <= NIBBLE_LENGTH as u64); + assert(length as u64 <= input.len() as u64); + + let mut nibble = [0 as u4; NIBBLE_LENGTH]; + + let first_nibble = (input[0] >> 4) as u4; + let parity = first_nibble as u1; + + if parity == 1 { + nibble[0] = (input[0] & 0x0f) as u4; + for i in 1..input.len() { + if i as u64 < length as u64 { + let x = input[i]; + nibble[2*i - 1] = (x >> 4) as u4; + nibble[2*i] = (x & 0x0f) as u4; + } + } + } else { + for i in 0..2 { + if (i as u64) < length as u64 - 1 { + let x = input[i + 1]; + nibble[2*i] = (x >> 4) as u4; + nibble[2*i + 1] = (x & 0x0f) as u4; + } + } + } + + let out = (nibble, 2 * length + (parity as Field) - 2); + + out +} + +fn enc(value: [u8; N], value_length: Field) -> ([u8; 32], Field) { + assert(value.len() as u8 >= value_length as u8); + let mut out_value = [0; 32]; + if value_length == 0 { + let out = (out_value, value_length); + out + } else if value_length as u8 < 31 { + out_value[0] = 0x80 + value_length as u8; + + for i in 1..value.len() { + out_value[i] = value[i-1]; + } + + let out = (out_value, value_length + 1); + + out + } else { + let out = (out_value, 32); + out + } +} + +fn bitshift_literal_0() -> u64 { + let mut bits: u64 = 0; + bits |= 1 << 0; + + bits +} +fn bitshift_literal_4() -> u64 { + let mut bits: u64 = 0; + bits |= 1 << 4; + + bits +} +fn bitshift_variable(idx: u64) -> u64 { + let mut bits: u64 = 0; + bits |= 1 << idx; + + bits +} + +fn main(x: [u8; 5], z: Field) { + //Issue 1144 + let (nib, len) = compact_decode(x, z); + assert(len == 5); + assert([nib[0], nib[1], nib[2], nib[3], nib[4]] == [15, 1, 12, 11, 8]); + // Issue 1169 + let val1 = [ + 0xb8, 0x8f, 0x61, 0xe6, 0xfb, 0xda, 0x83, 0xfb, 0xff, 0xfa, 0xbe, 0x36, 0x41, 0x12, 0x13, + 0x74, 0x80, 0x39, 0x80, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + ]; + let val1_length = 20; + + let enc_val1 = enc(val1, val1_length); + + assert( + enc_val1.0 == [ + 0x94, 0xb8, 0x8f, 0x61, 0xe6, 0xfb, 0xda, 0x83, 0xfb, 0xff, 0xfa, 0xbe, 0x36, 0x41, + 0x12, 0x13, 0x74, 0x80, 0x39, 0x80, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + ] + ); + assert(enc_val1.1 == 21); + // Issue 2399 + let result_0 = bitshift_literal_0(); + assert(result_0 == 1); + let result_4 = bitshift_literal_4(); + assert(result_4 == 16); + let result_0 = bitshift_variable(0); + assert(result_0 == 1); + let result_4 = bitshift_variable(4); + assert(result_4 == 16); +} diff --git a/test_programs/execution_success/regression_2660/Nargo.toml b/test_programs/execution_success/regression_2660/Nargo.toml new file mode 100644 index 0000000000..1ea0058684 --- /dev/null +++ b/test_programs/execution_success/regression_2660/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_2660" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/regression_2660/Prover.toml b/test_programs/execution_success/regression_2660/Prover.toml new file mode 100644 index 0000000000..4dd6b40515 --- /dev/null +++ b/test_programs/execution_success/regression_2660/Prover.toml @@ -0,0 +1 @@ +x = "1" diff --git a/test_programs/execution_success/regression_2660/src/main.nr b/test_programs/execution_success/regression_2660/src/main.nr new file mode 100644 index 0000000000..f32bc924e3 --- /dev/null +++ b/test_programs/execution_success/regression_2660/src/main.nr @@ -0,0 +1,6 @@ +global foo = -1; + +fn main(x: i32) { + let y = x + foo; + assert(y == 0); +} diff --git a/tooling/nargo_cli/tests/execution_success/regression_2854/Nargo.toml b/test_programs/execution_success/regression_2854/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/regression_2854/Nargo.toml rename to test_programs/execution_success/regression_2854/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/regression_2854/Prover.toml b/test_programs/execution_success/regression_2854/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/regression_2854/Prover.toml rename to test_programs/execution_success/regression_2854/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/regression_2854/src/main.nr b/test_programs/execution_success/regression_2854/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/regression_2854/src/main.nr rename to test_programs/execution_success/regression_2854/src/main.nr diff --git a/test_programs/execution_success/regression_3394/Nargo.toml b/test_programs/execution_success/regression_3394/Nargo.toml new file mode 100644 index 0000000000..4949962b16 --- /dev/null +++ b/test_programs/execution_success/regression_3394/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_3394" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/Prover.toml b/test_programs/execution_success/regression_3394/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/Prover.toml rename to test_programs/execution_success/regression_3394/Prover.toml diff --git a/test_programs/execution_success/regression_3394/src/main.nr b/test_programs/execution_success/regression_3394/src/main.nr new file mode 100644 index 0000000000..cc45487b98 --- /dev/null +++ b/test_programs/execution_success/regression_3394/src/main.nr @@ -0,0 +1,6 @@ +use dep::std; + +fn main() { + let x : i8 = -128; + std::println(x); +} \ No newline at end of file diff --git a/test_programs/execution_success/regression_3607/Nargo.toml b/test_programs/execution_success/regression_3607/Nargo.toml new file mode 100644 index 0000000000..8757f88b90 --- /dev/null +++ b/test_programs/execution_success/regression_3607/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_3607" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/execution_success/regression_3607/Prover.toml b/test_programs/execution_success/regression_3607/Prover.toml new file mode 100644 index 0000000000..4dd6b40515 --- /dev/null +++ b/test_programs/execution_success/regression_3607/Prover.toml @@ -0,0 +1 @@ +x = "1" diff --git a/test_programs/execution_success/regression_3607/src/main.nr b/test_programs/execution_success/regression_3607/src/main.nr new file mode 100644 index 0000000000..c09211c281 --- /dev/null +++ b/test_programs/execution_success/regression_3607/src/main.nr @@ -0,0 +1,8 @@ +fn main(mut x: u32) { + if x == 0 { + x = (x+1) / x; + } else { + x = (x+1) / x; + } + assert(x != 0); +} \ No newline at end of file diff --git a/test_programs/execution_success/regression_3635/Nargo.toml b/test_programs/execution_success/regression_3635/Nargo.toml new file mode 100644 index 0000000000..4f34121439 --- /dev/null +++ b/test_programs/execution_success/regression_3635/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_3635" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/Prover.toml b/test_programs/execution_success/regression_3635/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/Prover.toml rename to test_programs/execution_success/regression_3635/Prover.toml diff --git a/test_programs/execution_success/regression_3635/src/main.nr b/test_programs/execution_success/regression_3635/src/main.nr new file mode 100644 index 0000000000..97a04f9d93 --- /dev/null +++ b/test_programs/execution_success/regression_3635/src/main.nr @@ -0,0 +1,8 @@ +use dep::std; + +fn main() { + let x: u8 = 0x61; + let y: u8 = "a".as_bytes()[0]; + assert_eq(x, y); + assert_eq(x >> 1, y >> 1); +} diff --git a/tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/Nargo.toml b/test_programs/execution_success/regression_mem_op_predicate/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/Nargo.toml rename to test_programs/execution_success/regression_mem_op_predicate/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/Prover.toml b/test_programs/execution_success/regression_mem_op_predicate/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/Prover.toml rename to test_programs/execution_success/regression_mem_op_predicate/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/src/main.nr b/test_programs/execution_success/regression_mem_op_predicate/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/src/main.nr rename to test_programs/execution_success/regression_mem_op_predicate/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/Nargo.toml b/test_programs/execution_success/regression_method_cannot_be_found/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/Nargo.toml rename to test_programs/execution_success/regression_method_cannot_be_found/Nargo.toml diff --git a/test_programs/execution_success/regression_method_cannot_be_found/Prover.toml b/test_programs/execution_success/regression_method_cannot_be_found/Prover.toml new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/test_programs/execution_success/regression_method_cannot_be_found/Prover.toml @@ -0,0 +1 @@ + diff --git a/tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/src/main.nr b/test_programs/execution_success/regression_method_cannot_be_found/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/src/main.nr rename to test_programs/execution_success/regression_method_cannot_be_found/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/scalar_mul/Nargo.toml b/test_programs/execution_success/scalar_mul/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/scalar_mul/Nargo.toml rename to test_programs/execution_success/scalar_mul/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/scalar_mul/Prover.toml b/test_programs/execution_success/scalar_mul/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/scalar_mul/Prover.toml rename to test_programs/execution_success/scalar_mul/Prover.toml diff --git a/test_programs/execution_success/scalar_mul/src/main.nr b/test_programs/execution_success/scalar_mul/src/main.nr new file mode 100644 index 0000000000..2ddf22cf71 --- /dev/null +++ b/test_programs/execution_success/scalar_mul/src/main.nr @@ -0,0 +1,23 @@ +use dep::std; + +fn main( + a: Field, + a_pub_x: pub Field, + a_pub_y: pub Field, + b: Field, + b_pub_x: pub Field, + b_pub_y: pub Field +) { + let mut priv_key = a; + let mut pub_x: Field = a_pub_x; + let mut pub_y: Field = a_pub_y; + if a != 1 { + // Change `a` in Prover.toml to test input `b` + priv_key = b; + pub_x = b_pub_x; + pub_y = b_pub_y; + } + let res = std::scalar_mul::fixed_base_embedded_curve(priv_key, 0); + assert(res[0] == pub_x); + assert(res[1] == pub_y); +} diff --git a/tooling/nargo_cli/tests/execution_success/schnorr/Nargo.toml b/test_programs/execution_success/schnorr/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/schnorr/Nargo.toml rename to test_programs/execution_success/schnorr/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/schnorr/Prover.toml b/test_programs/execution_success/schnorr/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/schnorr/Prover.toml rename to test_programs/execution_success/schnorr/Prover.toml diff --git a/test_programs/execution_success/schnorr/src/main.nr b/test_programs/execution_success/schnorr/src/main.nr new file mode 100644 index 0000000000..107af15262 --- /dev/null +++ b/test_programs/execution_success/schnorr/src/main.nr @@ -0,0 +1,25 @@ +use dep::std; +// Note: If main has any unsized types, then the verifier will never be able +// to figure out the circuit instance +fn main( + message: [u8; 10], + message_field: Field, + pub_key_x: Field, + pub_key_y: Field, + signature: [u8; 64] +) { + // Regression for issue #2421 + // We want to make sure that we can accurately verify a signature whose message is a slice vs. an array + let message_field_bytes = message_field.to_be_bytes(10); + for i in 0..10 { + assert(message[i] == message_field_bytes[i]); + } + // Is there ever a situation where someone would want + // to ensure that a signature was invalid? + // Check that passing a slice as the message is valid + let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message_field_bytes); + assert(valid_signature); + // Check that passing an array as the message is valid + let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message); + assert(valid_signature); +} diff --git a/tooling/nargo_cli/tests/execution_success/sha256/Nargo.toml b/test_programs/execution_success/sha256/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/sha256/Nargo.toml rename to test_programs/execution_success/sha256/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/sha256/Prover.toml b/test_programs/execution_success/sha256/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/sha256/Prover.toml rename to test_programs/execution_success/sha256/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/sha256/src/main.nr b/test_programs/execution_success/sha256/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/sha256/src/main.nr rename to test_programs/execution_success/sha256/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/sha2_byte/Nargo.toml b/test_programs/execution_success/sha2_byte/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/sha2_byte/Nargo.toml rename to test_programs/execution_success/sha2_byte/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/sha2_byte/Prover.toml b/test_programs/execution_success/sha2_byte/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/sha2_byte/Prover.toml rename to test_programs/execution_success/sha2_byte/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/sha2_byte/src/main.nr b/test_programs/execution_success/sha2_byte/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/sha2_byte/src/main.nr rename to test_programs/execution_success/sha2_byte/src/main.nr diff --git a/test_programs/execution_success/side_effects_constrain_array/Nargo.toml b/test_programs/execution_success/side_effects_constrain_array/Nargo.toml new file mode 100644 index 0000000000..fc817f0921 --- /dev/null +++ b/test_programs/execution_success/side_effects_constrain_array/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "side_effects_constrain_array" +type = "bin" +authors = [""] +compiler_version = ">=0.20.0" + +[dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/slice_struct_field/Prover.toml b/test_programs/execution_success/side_effects_constrain_array/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/slice_struct_field/Prover.toml rename to test_programs/execution_success/side_effects_constrain_array/Prover.toml diff --git a/test_programs/execution_success/side_effects_constrain_array/src/main.nr b/test_programs/execution_success/side_effects_constrain_array/src/main.nr new file mode 100644 index 0000000000..fb3c346a46 --- /dev/null +++ b/test_programs/execution_success/side_effects_constrain_array/src/main.nr @@ -0,0 +1,17 @@ +struct Bar { + inner: [Field; 3], +} + +fn main(y: pub u32) { + let bar = Bar { inner: [100, 101, 102] }; + + // The assert inside the if should be hit + if y < 10 { + assert(bar.inner == [100, 101, 102]); + } + + // The assert inside the if should not be hit + if y > 10 { + assert(bar.inner == [0, 1, 2]); + } +} \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/signed_arithmetic/Nargo.toml b/test_programs/execution_success/signed_arithmetic/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/signed_arithmetic/Nargo.toml rename to test_programs/execution_success/signed_arithmetic/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/signed_arithmetic/Prover.toml b/test_programs/execution_success/signed_arithmetic/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/signed_arithmetic/Prover.toml rename to test_programs/execution_success/signed_arithmetic/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/signed_arithmetic/src/main.nr b/test_programs/execution_success/signed_arithmetic/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/signed_arithmetic/src/main.nr rename to test_programs/execution_success/signed_arithmetic/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/signed_division/Nargo.toml b/test_programs/execution_success/signed_division/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/signed_division/Nargo.toml rename to test_programs/execution_success/signed_division/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/signed_division/Prover.toml b/test_programs/execution_success/signed_division/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/signed_division/Prover.toml rename to test_programs/execution_success/signed_division/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/signed_division/src/main.nr b/test_programs/execution_success/signed_division/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/signed_division/src/main.nr rename to test_programs/execution_success/signed_division/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/simple_2d_array/Nargo.toml b/test_programs/execution_success/simple_2d_array/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_2d_array/Nargo.toml rename to test_programs/execution_success/simple_2d_array/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_2d_array/Prover.toml b/test_programs/execution_success/simple_2d_array/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_2d_array/Prover.toml rename to test_programs/execution_success/simple_2d_array/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_2d_array/src/main.nr b/test_programs/execution_success/simple_2d_array/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_2d_array/src/main.nr rename to test_programs/execution_success/simple_2d_array/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/simple_add_and_ret_arr/Nargo.toml b/test_programs/execution_success/simple_add_and_ret_arr/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_add_and_ret_arr/Nargo.toml rename to test_programs/execution_success/simple_add_and_ret_arr/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_add_and_ret_arr/Prover.toml b/test_programs/execution_success/simple_add_and_ret_arr/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_add_and_ret_arr/Prover.toml rename to test_programs/execution_success/simple_add_and_ret_arr/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_add_and_ret_arr/src/main.nr b/test_programs/execution_success/simple_add_and_ret_arr/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_add_and_ret_arr/src/main.nr rename to test_programs/execution_success/simple_add_and_ret_arr/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/simple_bitwise/Nargo.toml b/test_programs/execution_success/simple_bitwise/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_bitwise/Nargo.toml rename to test_programs/execution_success/simple_bitwise/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_bitwise/Prover.toml b/test_programs/execution_success/simple_bitwise/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_bitwise/Prover.toml rename to test_programs/execution_success/simple_bitwise/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_bitwise/src/main.nr b/test_programs/execution_success/simple_bitwise/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_bitwise/src/main.nr rename to test_programs/execution_success/simple_bitwise/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/simple_comparison/Nargo.toml b/test_programs/execution_success/simple_comparison/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_comparison/Nargo.toml rename to test_programs/execution_success/simple_comparison/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_comparison/Prover.toml b/test_programs/execution_success/simple_comparison/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_comparison/Prover.toml rename to test_programs/execution_success/simple_comparison/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_comparison/src/main.nr b/test_programs/execution_success/simple_comparison/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_comparison/src/main.nr rename to test_programs/execution_success/simple_comparison/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/simple_mut/Nargo.toml b/test_programs/execution_success/simple_mut/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_mut/Nargo.toml rename to test_programs/execution_success/simple_mut/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_mut/Prover.toml b/test_programs/execution_success/simple_mut/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_mut/Prover.toml rename to test_programs/execution_success/simple_mut/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_mut/src/main.nr b/test_programs/execution_success/simple_mut/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_mut/src/main.nr rename to test_programs/execution_success/simple_mut/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/simple_not/Nargo.toml b/test_programs/execution_success/simple_not/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_not/Nargo.toml rename to test_programs/execution_success/simple_not/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_not/Prover.toml b/test_programs/execution_success/simple_not/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_not/Prover.toml rename to test_programs/execution_success/simple_not/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_not/src/main.nr b/test_programs/execution_success/simple_not/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_not/src/main.nr rename to test_programs/execution_success/simple_not/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/simple_print/Nargo.toml b/test_programs/execution_success/simple_print/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_print/Nargo.toml rename to test_programs/execution_success/simple_print/Nargo.toml diff --git a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/Prover.toml b/test_programs/execution_success/simple_print/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/Prover.toml rename to test_programs/execution_success/simple_print/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_print/src/main.nr b/test_programs/execution_success/simple_print/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_print/src/main.nr rename to test_programs/execution_success/simple_print/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/simple_program_addition/Nargo.toml b/test_programs/execution_success/simple_program_addition/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_program_addition/Nargo.toml rename to test_programs/execution_success/simple_program_addition/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_program_addition/Prover.toml b/test_programs/execution_success/simple_program_addition/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_program_addition/Prover.toml rename to test_programs/execution_success/simple_program_addition/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_program_addition/src/main.nr b/test_programs/execution_success/simple_program_addition/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_program_addition/src/main.nr rename to test_programs/execution_success/simple_program_addition/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/simple_radix/Nargo.toml b/test_programs/execution_success/simple_radix/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_radix/Nargo.toml rename to test_programs/execution_success/simple_radix/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_radix/Prover.toml b/test_programs/execution_success/simple_radix/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_radix/Prover.toml rename to test_programs/execution_success/simple_radix/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_radix/src/main.nr b/test_programs/execution_success/simple_radix/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_radix/src/main.nr rename to test_programs/execution_success/simple_radix/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/simple_shield/Nargo.toml b/test_programs/execution_success/simple_shield/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_shield/Nargo.toml rename to test_programs/execution_success/simple_shield/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_shield/Prover.toml b/test_programs/execution_success/simple_shield/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_shield/Prover.toml rename to test_programs/execution_success/simple_shield/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_shield/src/main.nr b/test_programs/execution_success/simple_shield/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_shield/src/main.nr rename to test_programs/execution_success/simple_shield/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/simple_shift_left_right/Nargo.toml b/test_programs/execution_success/simple_shift_left_right/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_shift_left_right/Nargo.toml rename to test_programs/execution_success/simple_shift_left_right/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_shift_left_right/Prover.toml b/test_programs/execution_success/simple_shift_left_right/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_shift_left_right/Prover.toml rename to test_programs/execution_success/simple_shift_left_right/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/simple_shift_left_right/src/main.nr b/test_programs/execution_success/simple_shift_left_right/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/simple_shift_left_right/src/main.nr rename to test_programs/execution_success/simple_shift_left_right/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/slice_dynamic_index/Nargo.toml b/test_programs/execution_success/slice_dynamic_index/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/slice_dynamic_index/Nargo.toml rename to test_programs/execution_success/slice_dynamic_index/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/slice_dynamic_index/Prover.toml b/test_programs/execution_success/slice_dynamic_index/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/slice_dynamic_index/Prover.toml rename to test_programs/execution_success/slice_dynamic_index/Prover.toml diff --git a/test_programs/execution_success/slice_dynamic_index/src/main.nr b/test_programs/execution_success/slice_dynamic_index/src/main.nr new file mode 100644 index 0000000000..374d2ba4c2 --- /dev/null +++ b/test_programs/execution_success/slice_dynamic_index/src/main.nr @@ -0,0 +1,308 @@ +fn main(x: Field) { + // The parameters to this function must come directly from witness values (inputs to main). + regression_dynamic_slice_index(x - 1, x - 4); +} + +fn regression_dynamic_slice_index(x: Field, y: Field) { + let mut slice = []; + for i in 0..5 { + slice = slice.push_back(i); + } + assert(slice.len() == 5); + + dynamic_slice_index_set_if(slice, x, y); + dynamic_slice_index_set_else(slice, x, y); + dynamic_slice_index_set_nested_if_else_else(slice, x, y); + dynamic_slice_index_set_nested_if_else_if(slice, x, y + 1); + dynamic_slice_index_if(slice, x); + dynamic_array_index_if([0, 1, 2, 3, 4], x); + dynamic_slice_index_else(slice, x); + + dynamic_slice_merge_if(slice, x); + dynamic_slice_merge_else(slice, x); + dynamic_slice_merge_two_ifs(slice, x); + dynamic_slice_merge_mutate_between_ifs(slice, x, y); + dynamic_slice_merge_push_then_pop(slice, x, y); +} + +fn dynamic_slice_index_set_if(mut slice: [Field], x: Field, y: Field) { + assert(slice[x] == 4); + assert(slice[y] == 1); + slice[y] = 0; + assert(slice[x] == 4); + assert(slice[1] == 0); + if x as u32 < 10 { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + slice[x - 1] = slice[x]; + } else { + slice[x] = 0; + } + assert(slice[3] == 2); + assert(slice[4] == 2); +} + +fn dynamic_slice_index_set_else(mut slice: [Field], x: Field, y: Field) { + assert(slice[x] == 4); + assert(slice[y] == 1); + slice[y] = 0; + assert(slice[x] == 4); + assert(slice[1] == 0); + if x as u32 > 10 { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + slice[x - 1] = slice[x]; + } else { + slice[x] = 0; + } + assert(slice[4] == 0); +} +// This tests the case of missing a store instruction in the else branch +// of merging slices +fn dynamic_slice_index_if(mut slice: [Field], x: Field) { + if x as u32 < 10 { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + } else { + assert(slice[x] == 0); + } + assert(slice[4] == 2); +} + +fn dynamic_array_index_if(mut array: [Field; 5], x: Field) { + if x as u32 < 10 { + assert(array[x] == 4); + array[x] = array[x] - 2; + } else { + assert(array[x] == 0); + } + assert(array[4] == 2); +} +// This tests the case of missing a store instruction in the then branch +// of merging slices +fn dynamic_slice_index_else(mut slice: [Field], x: Field) { + if x as u32 > 10 { + assert(slice[x] == 0); + } else { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + } + assert(slice[4] == 2); +} + +fn dynamic_slice_merge_if(mut slice: [Field], x: Field) { + if x as u32 < 10 { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + + slice = slice.push_back(10); + // Having an array set here checks whether we appropriately + // handle a slice length that is not yet resolving to a constant + // during flattening + slice[x] = 10; + assert(slice[slice.len() - 1] == 10); + assert(slice.len() == 6); + + slice[x] = 20; + slice[x] = slice[x] + 10; + + slice = slice.push_front(11); + assert(slice[0] == 11); + assert(slice.len() == 7); + assert(slice[5] == 30); + + slice = slice.push_front(12); + assert(slice[0] == 12); + assert(slice.len() == 8); + assert(slice[6] == 30); + + let (popped_slice, last_elem) = slice.pop_back(); + assert(last_elem == 10); + assert(popped_slice.len() == 7); + + let (first_elem, rest_of_slice) = popped_slice.pop_front(); + assert(first_elem == 12); + assert(rest_of_slice.len() == 6); + + slice = rest_of_slice.insert(x - 2, 20); + assert(slice[2] == 20); + assert(slice[6] == 30); + assert(slice.len() == 7); + + let (removed_slice, removed_elem) = slice.remove(x - 1); + // The deconstructed tuple assigns to the slice but is not seen outside of the if statement + // without a direct assignment + slice = removed_slice; + + assert(removed_elem == 1); + assert(slice.len() == 6); + } else { + assert(slice[x] == 0); + slice = slice.push_back(20); + } + + assert(slice.len() == 6); + assert(slice[slice.len() - 1] == 30); +} + +fn dynamic_slice_merge_else(mut slice: [Field], x: Field) { + if x as u32 > 10 { + assert(slice[x] == 0); + slice[x] = 2; + } else { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + slice = slice.push_back(10); + } + assert(slice.len() == 6); + assert(slice[slice.len() - 1] == 10); + + slice = slice.push_back(20); + assert(slice.len() == 7); + assert(slice[slice.len() - 1] == 20); +} + +fn dynamic_slice_index_set_nested_if_else_else(mut slice: [Field], x: Field, y: Field) { + assert(slice[x] == 4); + assert(slice[y] == 1); + slice[y] = 0; + assert(slice[x] == 4); + assert(slice[1] == 0); + if x as u32 < 10 { + slice[x] = slice[x] - 2; + if y != 1 { + slice[x] = slice[x] + 20; + } else { + if x == 5 { + // We should not hit this case + assert(slice[x] == 22); + } else { + slice[x] = 10; + slice = slice.push_back(15); + assert(slice.len() == 6); + } + assert(slice[4] == 10); + } + } else { + slice[x] = 0; + } + assert(slice[4] == 10); + assert(slice.len() == 6); + assert(slice[slice.len() - 1] == 15); + + slice = slice.push_back(20); + assert(slice.len() == 7); + assert(slice[slice.len() - 1] == 20); +} + +fn dynamic_slice_index_set_nested_if_else_if(mut slice: [Field], x: Field, y: Field) { + assert(slice[x] == 4); + assert(slice[y] == 2); + slice[y] = 0; + assert(slice[x] == 4); + assert(slice[2] == 0); + if x as u32 < 10 { + slice[x] = slice[x] - 2; + // TODO: this panics as we have a load for the slice in flattening + if y == 1 { + slice[x] = slice[x] + 20; + } else { + if x == 4 { + slice[x] = 5; + } + assert(slice[4] == 5); + } + } else { + slice[x] = 0; + } + assert(slice[4] == 5); +} + +fn dynamic_slice_merge_two_ifs(mut slice: [Field], x: Field) { + if x as u32 > 10 { + assert(slice[x] == 0); + slice[x] = 2; + } else { + assert(slice[x] == 4); + slice[x] = slice[x] - 2; + slice = slice.push_back(10); + } + + assert(slice.len() == 6); + assert(slice[slice.len() - 1] == 10); + + if x == 20 { + slice = slice.push_back(20); + } + + slice = slice.push_back(15); + + assert(slice.len() == 7); + assert(slice[slice.len() - 1] == 15); + + slice = slice.push_back(20); + assert(slice.len() == 8); + assert(slice[slice.len() - 1] == 20); +} + +fn dynamic_slice_merge_mutate_between_ifs(mut slice: [Field], x: Field, y: Field) { + if x != y { + slice[x] = 50; + slice = slice.push_back(y); + slice = slice.push_back(x); + } else { + slice[x] = slice[x] - 2; + slice = slice.push_back(x); + } + + slice = slice.push_back(30); + assert(slice.len() == 8); + + if x == 20 { + slice = slice.push_back(20); + } + + slice = slice.push_back(15); + + if x != 20 { + slice = slice.push_back(50); + } + + slice = slice.push_back(60); + assert(slice.len() == 11); + assert(slice[x] == 50); + assert(slice[slice.len() - 4] == 30); + assert(slice[slice.len() - 3] == 15); + assert(slice[slice.len() - 2] == 50); + assert(slice[slice.len() - 1] == 60); +} + +fn dynamic_slice_merge_push_then_pop(mut slice: [Field], x: Field, y: Field) { + if x != y { + slice[x] = 5; + slice = slice.push_back(y); + slice = slice.push_back(x); + assert(slice.len() == 7); + + let (popped_slice, elem) = slice.pop_back(); + assert(slice.len() == 7); + assert(elem == x); + slice = popped_slice; + } else { + slice = slice.push_back(x); + } + + slice = slice.push_back(30); + assert(slice.len() == 7); + + if x == 20 { + slice = slice.push_back(20); + } + + let (slice, elem) = slice.pop_back(); + assert(elem == 30); + + let (_, elem) = slice.pop_back(); + assert(elem == y); +} + diff --git a/tooling/nargo_cli/tests/execution_success/slice_struct_field/Nargo.toml b/test_programs/execution_success/slice_struct_field/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/slice_struct_field/Nargo.toml rename to test_programs/execution_success/slice_struct_field/Nargo.toml diff --git a/test_programs/execution_success/slice_struct_field/Prover.toml b/test_programs/execution_success/slice_struct_field/Prover.toml new file mode 100644 index 0000000000..7127baac5b --- /dev/null +++ b/test_programs/execution_success/slice_struct_field/Prover.toml @@ -0,0 +1 @@ +y = "3" diff --git a/test_programs/execution_success/slice_struct_field/src/main.nr b/test_programs/execution_success/slice_struct_field/src/main.nr new file mode 100644 index 0000000000..a5b971ada4 --- /dev/null +++ b/test_programs/execution_success/slice_struct_field/src/main.nr @@ -0,0 +1,472 @@ +struct FooParent { + parent_arr: [Field; 3], + foos: [Foo], +} + +struct Bar { + inner: [Field; 3], +} + +struct Foo { + a: Field, + b: [Field], + bar: Bar, +} + +fn main(y: pub Field) { + let mut b_one = [2, 3, 20]; + b_one = b_one.push_back(20); + let foo_one = Foo { a: 1, b: b_one, bar: Bar { inner: [100, 101, 102] } }; + + let mut b_two = [5, 6, 21]; + b_two = b_two.push_back(21); + let foo_two = Foo { a: 4, b: b_two, bar: Bar { inner: [103, 104, 105] } }; + + let foo_three = Foo { a: 7, b: [8, 9, 22], bar: Bar { inner: [106, 107, 108] } }; + let mut foo_four = Foo { a: 10, b: [11, 12, 23], bar: Bar { inner: [109, 110, 111] } }; + + let mut x = [foo_one, foo_two]; + x = x.push_back(foo_three); + x = x.push_back(foo_four); + + assert(x[y - 3].a == 1); + let struct_slice = x[y - 3].b; + for i in 0..4 { + assert(struct_slice[i] == b_one[i]); + } + + assert(x[y - 2].a == 4); + let struct_slice = x[y - 2].b; + for i in 0..4 { + assert(struct_slice[i] == b_two[i]); + } + + assert(x[y - 1].a == 7); + let struct_slice = x[y - 1].b; + assert(struct_slice[0] == 8); + assert(struct_slice[1] == 9); + assert(struct_slice[2] == 22); + + assert(x[y].a == 10); + let struct_slice = x[y].b; + assert(struct_slice[0] == 11); + assert(struct_slice[1] == 12); + assert(struct_slice[2] == 23); + assert(x[y].bar.inner == [109, 110, 111]); + + assert(x[y - 3].bar.inner == [100, 101, 102]); + assert(x[y - 2].bar.inner == [103, 104, 105]); + assert(x[y - 1].bar.inner == [106, 107, 108]); + assert(x[y].bar.inner == [109, 110, 111]); + // Check that switching the lhs and rhs is still valid + assert([109, 110, 111] == x[y].bar.inner); + + assert(x[y - 3].bar.inner == [100, 101, 102]); + assert(x[y - 2].bar.inner == [103, 104, 105]); + assert(x[y - 1].bar.inner == [106, 107, 108]); + assert(x[y].bar.inner == [109, 110, 111]); + // Check that switching the lhs and rhs is still valid + assert([109, 110, 111] == x[y].bar.inner); + + // TODO: Enable merging nested slices + // if y != 2 { + // x[y].a = 50; + // } else { + // x[y].a = 100; + // } + // assert(x[3].a == 50); + // if y == 2 { + // x[y - 1].b = [50, 51, 52]; + // } else { + // x[y - 1].b = [100, 101, 102]; + // } + // assert(x[2].b[0] == 100); + // assert(x[2].b[1] == 101); + // assert(x[2].b[2] == 102); + + let q = x.push_back(foo_four); + let foo_parent_one = FooParent { parent_arr: [0, 1, 2], foos: x }; + let foo_parent_two = FooParent { parent_arr: [3, 4, 5], foos: q }; + let mut foo_parents = [foo_parent_one]; + foo_parents = foo_parents.push_back(foo_parent_two); + // TODO: make a separate test for entirely compile time + // foo_parents[1].foos.push_back(foo_four); + // TODO: Merging nested slices is broken + // if y == 3 { + // foo_parents[y - 2].foos[y - 1].b[y - 1] = 5000; + // } else { + // foo_parents[y - 2].foos[y - 1].b[y - 1] = 1000; + // } + + assert(foo_parents[y - 2].foos[y - 2].b[y - 1] == 21); + foo_parents[y - 2].foos[y - 2].b[y - 1] = 5000; + assert(foo_parents[y - 2].foos[y - 2].b[y - 1] == 5000); + + let b_array = foo_parents[y - 2].foos[y - 3].b; + assert(foo_parents[y - 2].foos[y - 3].a == 1); + assert(b_array[0] == 2); + assert(b_array[1] == 3); + assert(b_array[2] == 20); + assert(b_array[3] == 20); + + let b_array = foo_parents[y - 2].foos[y - 2].b; + assert(foo_parents[y - 2].foos[y - 2].a == 4); + assert(b_array[0] == 5); + assert(b_array[1] == 6); + assert(b_array[2] == 5000); + assert(b_array[3] == 21); + + assert(foo_parents[y - 2].foos[y - 1].a == 7); + foo_parents[y - 2].foos[y - 1].a = 50; + assert(foo_parents[y - 2].foos[y - 1].a == 50); + + let b_array = foo_parents[y - 2].foos[y - 1].b; + assert(b_array[0] == 8); + assert(b_array[1] == 9); + assert(b_array[2] == 22); + assert(b_array.len() == 3); + + // // Test setting a nested array with non-dynamic + let x = [5, 6, 5000, 21, 100, 101].as_slice(); + foo_parents[y - 2].foos[y - 1].b = x; + + assert(foo_parents[y - 2].foos[y - 1].b.len() == 6); + assert(foo_parents[y - 2].foos[y - 1].b[4] == 100); + assert(foo_parents[y - 2].foos[y - 1].b[5] == 101); + + // Need to account for that foo_parents is not modified outside of this function + test_basic_intrinsics_nested_slices(foo_parents, y); + test_complex_intrinsic_nested_slices(foo_parents, y); + + foo_parents[y - 2].foos[y - 1].b = foo_parents[y - 2].foos[y - 1].b.push_back(500); + assert(foo_parents[y - 2].foos[y - 1].b.len() == 7); + assert(foo_parents[y - 2].foos[y - 1].b[6] == 500); + + let (popped_slice, last_elem) = foo_parents[y - 2].foos[y - 1].b.pop_back(); + foo_parents[y - 2].foos[y - 1].b = popped_slice; + assert(foo_parents[y - 2].foos[y - 1].b.len() == 6); + assert(last_elem == 500); + + foo_parents[y - 2].foos[y - 1].b = foo_parents[y - 2].foos[y - 1].b.push_front(11); + assert(foo_parents[y - 2].foos[y - 1].b.len() == 7); + assert(foo_parents[y - 2].foos[y - 1].b[0] == 11); + + assert(foo_parents[y - 2].foos.len() == 5); + foo_four.a = 40; + foo_parents[y - 2].foos = foo_parents[y - 2].foos.push_back(foo_four); + assert(foo_parents[y - 2].foos.len() == 6); + assert(foo_parents[y - 2].foos[y + 2].bar.inner == [109, 110, 111]); + + foo_parents[y - 2].foos = foo_parents[y - 2].foos.push_back(foo_four); + assert(foo_parents[y - 2].foos.len() == 7); + assert(foo_parents[y - 2].foos[6].a == 40); + assert(foo_parents[y - 2].foos[5].bar.inner == [109, 110, 111]); + assert(foo_parents[y - 2].foos[6].bar.inner == [109, 110, 111]); + + foo_parents[y - 2].foos = foo_parents[y - 2].foos.push_back(foo_four); + assert(foo_parents[y - 2].foos.len() == 8); + assert(foo_parents[y - 2].foos[6].a == 40); + assert(foo_parents[y - 2].foos[5].bar.inner == [109, 110, 111]); + assert(foo_parents[y - 2].foos[6].bar.inner == [109, 110, 111]); + + foo_parents[y - 2].foos = foo_parents[y - 2].foos.push_back(foo_four); + assert(foo_parents[y - 2].foos.len() == 9); + + foo_parents[y - 2].foos = foo_parents[y - 2].foos.push_back(foo_four); + assert(foo_parents[y - 2].foos.len() == 10); + + let b_array = foo_parents[y - 2].foos[y - 1].b; + assert(b_array[0] == 11); + assert(b_array[1] == 5); + assert(b_array[2] == 6); + assert(b_array[3] == 5000); + + let b_array = foo_parents[y - 2].foos[y].b; + assert(foo_parents[y - 2].foos[y].a == 10); + assert(b_array[0] == 11); + assert(b_array[1] == 12); + assert(b_array[2] == 23); + + assert(foo_parents[y - 2].foos[y - 3].bar.inner == [100, 101, 102]); + assert(foo_parents[y - 2].foos[y - 2].bar.inner == [103, 104, 105]); + assert(foo_parents[y - 2].foos[y - 1].bar.inner == [106, 107, 108]); + assert(foo_parents[y - 2].foos[y].bar.inner == [109, 110, 111]); +} + +fn test_basic_intrinsics_nested_slices(mut foo_parents: [FooParent], y: Field) { + foo_parents[y - 2].foos[y - 1].b = foo_parents[y - 2].foos[y - 1].b.push_back(500); + assert(foo_parents[y - 2].foos[y - 1].b.len() == 7); + assert(foo_parents[y - 2].foos[y - 1].b[6] == 500); + + let (popped_slice, last_elem) = foo_parents[y - 2].foos[y - 1].b.pop_back(); + foo_parents[y - 2].foos[y - 1].b = popped_slice; + assert(foo_parents[y - 2].foos[y - 1].b.len() == 6); + assert(last_elem == 500); + + foo_parents[y - 2].foos[y - 1].b = foo_parents[y - 2].foos[y - 1].b.push_front(11); + assert(foo_parents[y - 2].foos[y - 1].b.len() == 7); + assert(foo_parents[y - 2].foos[y - 1].b[0] == 11); + + let (first_elem, rest_of_slice) = foo_parents[y - 2].foos[y - 1].b.pop_front(); + foo_parents[y - 2].foos[y - 1].b = rest_of_slice; + assert(foo_parents[y - 2].foos[y - 1].b.len() == 6); + assert(first_elem == 11); + + foo_parents[y - 2].foos[y - 1].b = foo_parents[y - 2].foos[y - 1].b.insert(2, 20); + assert(foo_parents[y - 2].foos[y - 1].b.len() == 7); + assert(foo_parents[y - 2].foos[y - 1].b[y - 1] == 20); + assert(foo_parents[y - 2].foos[y - 1].b[y] == 5000); + assert(foo_parents[y - 2].foos[y - 1].b[6] == 101); + + let (rest_of_slice, removed_elem) = foo_parents[y - 2].foos[y - 1].b.remove(3); + foo_parents[y - 2].foos[y - 1].b = rest_of_slice; + assert(removed_elem == 5000); + assert(foo_parents[y - 2].foos[y - 1].b.len() == 6); + assert(foo_parents[y - 2].foos[y - 1].b[2] == 20); + assert(foo_parents[y - 2].foos[y - 1].b[3] == 21); +} + +// This method test intrinsics on nested slices with complex inputs such as +// pushing a `Foo` struct onto a slice in `FooParents`. +fn test_complex_intrinsic_nested_slices(mut foo_parents: [FooParent], y: Field) { + let mut foo = Foo { a: 13, b: [14, 15, 16], bar: Bar { inner: [109, 110, 111] } }; + assert(foo_parents[y - 2].foos.len() == 5); + foo.a = 40; + foo_parents[y - 2].foos = foo_parents[y - 2].foos.push_back(foo); + assert(foo_parents[1].foos.len() == 6); + assert(foo_parents[1].foos[5].a == 40); + assert(foo_parents[1].foos[5].b[0] == 14); + assert(foo_parents[1].foos[5].b[2] == 16); + assert(foo_parents[1].foos[5].b.len() == 3); + assert(foo_parents[1].foos[5].bar.inner == [109, 110, 111]); + + foo_parents[y - 2].foos[y - 1].b = foo_parents[y - 2].foos[y - 1].b.push_back(500); + assert(foo_parents[1].foos[2].b.len() == 7); + assert(foo_parents[1].foos[2].b[6] == 500); + assert(foo_parents[1].foos[2].bar.inner == [106, 107, 108]); + assert(foo_parents[1].foos[5].a == 40); + assert(foo_parents[1].foos[5].b[0] == 14); + assert(foo_parents[1].foos[5].b[2] == 16); + assert(foo_parents[1].foos[5].b.len() == 3); + assert(foo_parents[1].foos[5].bar.inner == [109, 110, 111]); + + let (popped_slice, last_foo) = foo_parents[y - 2].foos.pop_back(); + foo_parents[y - 2].foos = popped_slice; + assert(foo_parents[y - 2].foos.len() == 5); + assert(last_foo.a == 40); + assert(last_foo.b[0] == 14); + assert(last_foo.b[1] == 15); + assert(last_foo.b[2] == 16); + assert(last_foo.bar.inner == [109, 110, 111]); + + foo_parents[y - 2].foos = foo_parents[y - 2].foos.push_front(foo); + assert(foo_parents[1].foos.len() == 6); + assert(foo_parents[1].foos[0].a == 40); + assert(foo_parents[1].foos[0].b[0] == 14); + assert(foo_parents[1].foos[0].b[1] == 15); + assert(foo_parents[1].foos[0].b[2] == 16); + assert(foo_parents[1].foos[5].a == 10); + assert(foo_parents[1].foos[5].b.len() == 3); + assert(foo_parents[1].foos[5].b[0] == 11); + assert(foo_parents[1].foos[5].b[2] == 23); + assert(foo_parents[1].foos[5].bar.inner == [109, 110, 111]); + + assert(foo_parents[1].foos[1].a == 1); + assert(foo_parents[1].foos[1].bar.inner == [100, 101, 102]); + + let (first_foo, rest_of_slice) = foo_parents[y - 2].foos.pop_front(); + + foo_parents[y - 2].foos = rest_of_slice; + assert(first_foo.a == 40); + assert(first_foo.b[0] == 14); + assert(first_foo.b[1] == 15); + assert(first_foo.b[2] == 16); + assert(first_foo.bar.inner == [109, 110, 111]); + + assert(foo_parents[1].foos[0].a == 1); + assert(foo_parents[1].foos[0].b[0] == 2); + assert(foo_parents[1].foos[0].b[1] == 3); + assert(foo_parents[1].foos[0].b[2] == 20); + assert(foo_parents[1].foos[0].b[3] == 20); + assert(foo_parents[1].foos[0].bar.inner == [100, 101, 102]); + + test_insert_remove_const_index(foo_parents, y, foo); + + // Check values before insertion + assert(foo_parents[1].foos[1].a == 4); + assert(foo_parents[1].foos[1].b[0] == 5); + assert(foo_parents[1].foos[1].b[1] == 6); + assert(foo_parents[1].foos[1].b[2] == 5000); + assert(foo_parents[1].foos[1].b[3] == 21); + assert(foo_parents[1].foos[1].bar.inner == [103, 104, 105]); + + assert(foo_parents[1].foos.len() == 5); + assert(foo_parents[1].foos[2].a == 50); + assert(foo_parents[1].foos[2].b[0] == 5); + assert(foo_parents[1].foos[2].b[2] == 5000); + assert(foo_parents[1].foos[2].bar.inner == [106, 107, 108]); + + assert(foo_parents[1].foos[3].a == 10); + assert(foo_parents[1].foos[3].b[0] == 11); + assert(foo_parents[1].foos[3].b[2] == 23); + assert(foo_parents[1].foos[3].bar.inner == [109, 110, 111]); + + foo_parents[y - 2].foos = foo_parents[y - 2].foos.insert(y - 1, foo); + assert(foo_parents[1].foos.len() == 6); + + // Check values correctly moved after insertion + assert(foo_parents[1].foos[0].a == 1); + assert(foo_parents[1].foos[0].b[0] == 2); + assert(foo_parents[1].foos[0].b[1] == 3); + assert(foo_parents[1].foos[0].b[2] == 20); + assert(foo_parents[1].foos[0].b[3] == 20); + assert(foo_parents[1].foos[0].bar.inner == [100, 101, 102]); + + assert(foo_parents[1].foos[1].a == 4); + assert(foo_parents[1].foos[1].b[0] == 5); + assert(foo_parents[1].foos[1].b[1] == 6); + assert(foo_parents[1].foos[1].b[2] == 5000); + assert(foo_parents[1].foos[1].b[3] == 21); + assert(foo_parents[1].foos[1].bar.inner == [103, 104, 105]); + + assert(foo_parents[1].foos[2].a == 40); + assert(foo_parents[1].foos[2].b[0] == 14); + assert(foo_parents[1].foos[2].b[2] == 16); + assert(foo_parents[1].foos[2].bar.inner == [109, 110, 111]); + + assert(foo_parents[1].foos[3].a == 50); + assert(foo_parents[1].foos[3].b[0] == 5); + assert(foo_parents[1].foos[3].b[2] == 5000); + assert(foo_parents[1].foos[3].bar.inner == [106, 107, 108]); + + assert(foo_parents[1].foos[4].a == 10); + assert(foo_parents[1].foos[4].b[0] == 11); + assert(foo_parents[1].foos[4].b[2] == 23); + assert(foo_parents[1].foos[4].bar.inner == [109, 110, 111]); + + assert(foo_parents[1].foos[5].a == 10); + assert(foo_parents[1].foos[5].b[0] == 11); + assert(foo_parents[1].foos[5].b[2] == 23); + assert(foo_parents[1].foos[5].bar.inner == [109, 110, 111]); + + let (rest_of_slice, removed_elem) = foo_parents[y - 2].foos.remove(y - 1); + foo_parents[1].foos = rest_of_slice; + + // Check that the accurate element was removed + assert(removed_elem.a == 40); + assert(removed_elem.b[0] == 14); + assert(removed_elem.b[2] == 16); + assert(removed_elem.bar.inner == [109, 110, 111]); + + // Check that we have altered our slice accurately following a removal + assert(foo_parents[1].foos[1].a == 4); + assert(foo_parents[1].foos[1].b[0] == 5); + assert(foo_parents[1].foos[1].b[1] == 6); + assert(foo_parents[1].foos[1].b[2] == 5000); + assert(foo_parents[1].foos[1].b[3] == 21); + assert(foo_parents[1].foos[1].bar.inner == [103, 104, 105]); + + assert(foo_parents[1].foos[2].a == 50); + assert(foo_parents[1].foos[2].b[0] == 5); + assert(foo_parents[1].foos[2].b[2] == 5000); + assert(foo_parents[1].foos[2].bar.inner == [106, 107, 108]); + + assert(foo_parents[1].foos[3].a == 10); + assert(foo_parents[1].foos[3].b[0] == 11); + assert(foo_parents[1].foos[3].b[2] == 23); + assert(foo_parents[1].foos[3].bar.inner == [109, 110, 111]); + + assert(foo_parents[1].foos[4].b[0] == 11); + assert(foo_parents[1].foos[4].b[2] == 23); + assert(foo_parents[1].foos[4].bar.inner == [109, 110, 111]); +} + +fn test_insert_remove_const_index(mut foo_parents: [FooParent], y: Field, foo: Foo) { + // Check values before insertion + assert(foo_parents[1].foos[1].a == 4); + assert(foo_parents[1].foos[1].b[0] == 5); + assert(foo_parents[1].foos[1].b[1] == 6); + assert(foo_parents[1].foos[1].b[2] == 5000); + assert(foo_parents[1].foos[1].b[3] == 21); + assert(foo_parents[1].foos[1].bar.inner == [103, 104, 105]); + + assert(foo_parents[1].foos.len() == 5); + assert(foo_parents[1].foos[2].a == 50); + assert(foo_parents[1].foos[2].b[0] == 5); + assert(foo_parents[1].foos[2].b[2] == 5000); + assert(foo_parents[1].foos[2].bar.inner == [106, 107, 108]); + + assert(foo_parents[1].foos[3].a == 10); + assert(foo_parents[1].foos[3].b[0] == 11); + assert(foo_parents[1].foos[3].b[2] == 23); + assert(foo_parents[1].foos[3].bar.inner == [109, 110, 111]); + + foo_parents[y - 2].foos = foo_parents[y - 2].foos.insert(2, foo); + assert(foo_parents[1].foos.len() == 6); + + // Check values correctly moved after insertion + assert(foo_parents[1].foos[0].a == 1); + assert(foo_parents[1].foos[0].b[0] == 2); + assert(foo_parents[1].foos[0].b[1] == 3); + assert(foo_parents[1].foos[0].b[2] == 20); + assert(foo_parents[1].foos[0].b[3] == 20); + assert(foo_parents[1].foos[0].bar.inner == [100, 101, 102]); + + assert(foo_parents[1].foos[1].a == 4); + assert(foo_parents[1].foos[1].b[0] == 5); + assert(foo_parents[1].foos[1].b[1] == 6); + assert(foo_parents[1].foos[1].b[2] == 5000); + assert(foo_parents[1].foos[1].b[3] == 21); + assert(foo_parents[1].foos[1].bar.inner == [103, 104, 105]); + + assert(foo_parents[1].foos[2].a == 40); + assert(foo_parents[1].foos[2].b[0] == 14); + assert(foo_parents[1].foos[2].b[2] == 16); + assert(foo_parents[1].foos[2].bar.inner == [109, 110, 111]); + + assert(foo_parents[1].foos[3].a == 50); + assert(foo_parents[1].foos[3].b[0] == 5); + assert(foo_parents[1].foos[3].b[2] == 5000); + assert(foo_parents[1].foos[3].bar.inner == [106, 107, 108]); + + assert(foo_parents[1].foos[4].a == 10); + assert(foo_parents[1].foos[4].b[0] == 11); + assert(foo_parents[1].foos[4].b[2] == 23); + assert(foo_parents[1].foos[4].bar.inner == [109, 110, 111]); + + assert(foo_parents[1].foos[5].a == 10); + assert(foo_parents[1].foos[5].b[0] == 11); + assert(foo_parents[1].foos[5].b[2] == 23); + assert(foo_parents[1].foos[5].bar.inner == [109, 110, 111]); + + let (rest_of_slice, removed_elem) = foo_parents[y - 2].foos.remove(2); + foo_parents[1].foos = rest_of_slice; + + // Check that the accurate element was removed + assert(removed_elem.a == 40); + assert(removed_elem.b[0] == 14); + assert(removed_elem.b[2] == 16); + assert(removed_elem.bar.inner == [109, 110, 111]); + + // Check that we have altered our slice accurately following a removal + assert(foo_parents[1].foos[1].a == 4); + assert(foo_parents[1].foos[1].b[0] == 5); + assert(foo_parents[1].foos[1].b[1] == 6); + assert(foo_parents[1].foos[1].b[2] == 5000); + assert(foo_parents[1].foos[1].b[3] == 21); + assert(foo_parents[1].foos[1].bar.inner == [103, 104, 105]); + + assert(foo_parents[1].foos[2].a == 50); + assert(foo_parents[1].foos[2].b[0] == 5); + assert(foo_parents[1].foos[2].b[2] == 5000); + assert(foo_parents[1].foos[2].bar.inner == [106, 107, 108]); + + assert(foo_parents[1].foos[3].a == 10); + assert(foo_parents[1].foos[3].b[0] == 11); + assert(foo_parents[1].foos[3].b[2] == 23); + assert(foo_parents[1].foos[3].bar.inner == [109, 110, 111]); + + assert(foo_parents[1].foos[4].b[0] == 11); + assert(foo_parents[1].foos[4].b[2] == 23); + assert(foo_parents[1].foos[4].bar.inner == [109, 110, 111]); +} diff --git a/tooling/nargo_cli/tests/execution_success/slices/Nargo.toml b/test_programs/execution_success/slices/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/slices/Nargo.toml rename to test_programs/execution_success/slices/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/slices/Prover.toml b/test_programs/execution_success/slices/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/slices/Prover.toml rename to test_programs/execution_success/slices/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/slices/src/main.nr b/test_programs/execution_success/slices/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/slices/src/main.nr rename to test_programs/execution_success/slices/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/strings/Nargo.toml b/test_programs/execution_success/strings/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/strings/Nargo.toml rename to test_programs/execution_success/strings/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/strings/Prover.toml b/test_programs/execution_success/strings/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/strings/Prover.toml rename to test_programs/execution_success/strings/Prover.toml diff --git a/test_programs/execution_success/strings/src/main.nr b/test_programs/execution_success/strings/src/main.nr new file mode 100644 index 0000000000..cff229d368 --- /dev/null +++ b/test_programs/execution_success/strings/src/main.nr @@ -0,0 +1,85 @@ +use dep::std; +// Test global string literals +global HELLO_WORLD = "hello world"; + +fn main(message: pub str<11>, y: Field, hex_as_string: str<4>, hex_as_field: Field) { + let mut bad_message = "hello world"; + + assert(message == "hello world"); + assert(message == HELLO_WORLD); + let x = 10; + let z = x * 5; + std::println(10); + std::print(10); + + std::println(z); // x * 5 in println not yet supported + std::print(z); + std::println(x); + std::print(x); + + let array = [1, 2, 3, 5, 8]; + assert(y == 5); // Change to y != 5 to see how the later print statements are not called + std::println(array); + std::print(array); + + bad_message = "hell\0\"world"; + std::println(bad_message); + std::print(bad_message); + assert(message != bad_message); + + let hash = std::hash::pedersen_commitment([x]); + std::println(hash); + std::print(hash); + + assert(hex_as_string == "0x41"); + // assert(hex_as_string != 0x41); This will fail with a type mismatch between str[4] and Field + assert(hex_as_field == 0x41); + + // Single digit & odd length hex literals are valid + assert(hex_as_field == 0x041); + assert(hex_as_field != 0x1); +} + +#[test] +fn test_prints_strings() { + let message = "hello world!"; + + std::println(message); + std::println("goodbye world"); + + std::print(message); + std::print("\n"); + std::print("goodbye world\n"); +} + +#[test] +fn test_prints_array() { + let array = [1, 2, 3, 5, 8]; + + let s = Test { a: 1, b: 2, c: [3, 4] }; + std::println(s); + + std::println(array); + + let hash = std::hash::pedersen_commitment(array); + std::println(hash); +} + +fn failed_constraint(hex_as_field: Field) { + // When this method is called from a test method or with constant values + // a `Failed constraint` compile error will be caught before this `println` + // is executed as the input will be a constant. + std::println(hex_as_field); + assert(hex_as_field != 0x41); +} + +#[test] +fn test_failed_constraint() { + failed_constraint(0x41); +} + +struct Test { + a: Field, + b: Field, + c: [Field; 2], +} diff --git a/tooling/nargo_cli/tests/execution_success/struct/Nargo.toml b/test_programs/execution_success/struct/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct/Nargo.toml rename to test_programs/execution_success/struct/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/struct/Prover.toml b/test_programs/execution_success/struct/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct/Prover.toml rename to test_programs/execution_success/struct/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/struct/src/main.nr b/test_programs/execution_success/struct/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct/src/main.nr rename to test_programs/execution_success/struct/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/struct_array_inputs/Nargo.toml b/test_programs/execution_success/struct_array_inputs/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct_array_inputs/Nargo.toml rename to test_programs/execution_success/struct_array_inputs/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/struct_array_inputs/Prover.toml b/test_programs/execution_success/struct_array_inputs/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct_array_inputs/Prover.toml rename to test_programs/execution_success/struct_array_inputs/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/struct_array_inputs/src/main.nr b/test_programs/execution_success/struct_array_inputs/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct_array_inputs/src/main.nr rename to test_programs/execution_success/struct_array_inputs/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/struct_fields_ordering/Nargo.toml b/test_programs/execution_success/struct_fields_ordering/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct_fields_ordering/Nargo.toml rename to test_programs/execution_success/struct_fields_ordering/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/struct_fields_ordering/Prover.toml b/test_programs/execution_success/struct_fields_ordering/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct_fields_ordering/Prover.toml rename to test_programs/execution_success/struct_fields_ordering/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/struct_fields_ordering/src/main.nr b/test_programs/execution_success/struct_fields_ordering/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct_fields_ordering/src/main.nr rename to test_programs/execution_success/struct_fields_ordering/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/struct_inputs/Nargo.toml b/test_programs/execution_success/struct_inputs/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct_inputs/Nargo.toml rename to test_programs/execution_success/struct_inputs/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/struct_inputs/Prover.toml b/test_programs/execution_success/struct_inputs/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct_inputs/Prover.toml rename to test_programs/execution_success/struct_inputs/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/struct_inputs/src/foo.nr b/test_programs/execution_success/struct_inputs/src/foo.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct_inputs/src/foo.nr rename to test_programs/execution_success/struct_inputs/src/foo.nr diff --git a/tooling/nargo_cli/tests/execution_success/struct_inputs/src/foo/bar.nr b/test_programs/execution_success/struct_inputs/src/foo/bar.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct_inputs/src/foo/bar.nr rename to test_programs/execution_success/struct_inputs/src/foo/bar.nr diff --git a/tooling/nargo_cli/tests/execution_success/struct_inputs/src/main.nr b/test_programs/execution_success/struct_inputs/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/struct_inputs/src/main.nr rename to test_programs/execution_success/struct_inputs/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/submodules/Nargo.toml b/test_programs/execution_success/submodules/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/submodules/Nargo.toml rename to test_programs/execution_success/submodules/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/submodules/Prover.toml b/test_programs/execution_success/submodules/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/submodules/Prover.toml rename to test_programs/execution_success/submodules/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/submodules/src/main.nr b/test_programs/execution_success/submodules/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/submodules/src/main.nr rename to test_programs/execution_success/submodules/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/to_be_bytes/Nargo.toml b/test_programs/execution_success/to_be_bytes/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/to_be_bytes/Nargo.toml rename to test_programs/execution_success/to_be_bytes/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/to_be_bytes/Prover.toml b/test_programs/execution_success/to_be_bytes/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/to_be_bytes/Prover.toml rename to test_programs/execution_success/to_be_bytes/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/to_be_bytes/src/main.nr b/test_programs/execution_success/to_be_bytes/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/to_be_bytes/src/main.nr rename to test_programs/execution_success/to_be_bytes/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/to_bytes_consistent/Nargo.toml b/test_programs/execution_success/to_bytes_consistent/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/to_bytes_consistent/Nargo.toml rename to test_programs/execution_success/to_bytes_consistent/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/to_bytes_consistent/Prover.toml b/test_programs/execution_success/to_bytes_consistent/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/to_bytes_consistent/Prover.toml rename to test_programs/execution_success/to_bytes_consistent/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/to_bytes_consistent/src/main.nr b/test_programs/execution_success/to_bytes_consistent/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/to_bytes_consistent/src/main.nr rename to test_programs/execution_success/to_bytes_consistent/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/to_bytes_integration/Nargo.toml b/test_programs/execution_success/to_bytes_integration/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/to_bytes_integration/Nargo.toml rename to test_programs/execution_success/to_bytes_integration/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/to_bytes_integration/Prover.toml b/test_programs/execution_success/to_bytes_integration/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/to_bytes_integration/Prover.toml rename to test_programs/execution_success/to_bytes_integration/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/to_bytes_integration/src/main.nr b/test_programs/execution_success/to_bytes_integration/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/to_bytes_integration/src/main.nr rename to test_programs/execution_success/to_bytes_integration/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/to_le_bytes/Nargo.toml b/test_programs/execution_success/to_le_bytes/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/to_le_bytes/Nargo.toml rename to test_programs/execution_success/to_le_bytes/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/to_le_bytes/Prover.toml b/test_programs/execution_success/to_le_bytes/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/to_le_bytes/Prover.toml rename to test_programs/execution_success/to_le_bytes/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/to_le_bytes/src/main.nr b/test_programs/execution_success/to_le_bytes/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/to_le_bytes/src/main.nr rename to test_programs/execution_success/to_le_bytes/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/trait_as_return_type/Nargo.toml b/test_programs/execution_success/trait_as_return_type/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/trait_as_return_type/Nargo.toml rename to test_programs/execution_success/trait_as_return_type/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/trait_as_return_type/Prover.toml b/test_programs/execution_success/trait_as_return_type/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/trait_as_return_type/Prover.toml rename to test_programs/execution_success/trait_as_return_type/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/trait_as_return_type/src/main.nr b/test_programs/execution_success/trait_as_return_type/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/trait_as_return_type/src/main.nr rename to test_programs/execution_success/trait_as_return_type/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/trait_impl_base_type/Nargo.toml b/test_programs/execution_success/trait_impl_base_type/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/trait_impl_base_type/Nargo.toml rename to test_programs/execution_success/trait_impl_base_type/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/trait_impl_base_type/Prover.toml b/test_programs/execution_success/trait_impl_base_type/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/trait_impl_base_type/Prover.toml rename to test_programs/execution_success/trait_impl_base_type/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/trait_impl_base_type/src/main.nr b/test_programs/execution_success/trait_impl_base_type/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/trait_impl_base_type/src/main.nr rename to test_programs/execution_success/trait_impl_base_type/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/Nargo.toml b/test_programs/execution_success/traits_in_crates_1/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_1/Nargo.toml rename to test_programs/execution_success/traits_in_crates_1/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/Prover.toml b/test_programs/execution_success/traits_in_crates_1/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_1/Prover.toml rename to test_programs/execution_success/traits_in_crates_1/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate1/Nargo.toml b/test_programs/execution_success/traits_in_crates_1/crate1/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate1/Nargo.toml rename to test_programs/execution_success/traits_in_crates_1/crate1/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate1/src/lib.nr b/test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate1/src/lib.nr rename to test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate2/Nargo.toml b/test_programs/execution_success/traits_in_crates_1/crate2/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate2/Nargo.toml rename to test_programs/execution_success/traits_in_crates_1/crate2/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate2/src/lib.nr b/test_programs/execution_success/traits_in_crates_1/crate2/src/lib.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate2/src/lib.nr rename to test_programs/execution_success/traits_in_crates_1/crate2/src/lib.nr diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/src/main.nr b/test_programs/execution_success/traits_in_crates_1/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_1/src/main.nr rename to test_programs/execution_success/traits_in_crates_1/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/Nargo.toml b/test_programs/execution_success/traits_in_crates_2/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_2/Nargo.toml rename to test_programs/execution_success/traits_in_crates_2/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/Prover.toml b/test_programs/execution_success/traits_in_crates_2/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_2/Prover.toml rename to test_programs/execution_success/traits_in_crates_2/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate1/Nargo.toml b/test_programs/execution_success/traits_in_crates_2/crate1/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate1/Nargo.toml rename to test_programs/execution_success/traits_in_crates_2/crate1/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate1/src/lib.nr b/test_programs/execution_success/traits_in_crates_2/crate1/src/lib.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate1/src/lib.nr rename to test_programs/execution_success/traits_in_crates_2/crate1/src/lib.nr diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate2/Nargo.toml b/test_programs/execution_success/traits_in_crates_2/crate2/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate2/Nargo.toml rename to test_programs/execution_success/traits_in_crates_2/crate2/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate2/src/lib.nr b/test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate2/src/lib.nr rename to test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/src/main.nr b/test_programs/execution_success/traits_in_crates_2/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/traits_in_crates_2/src/main.nr rename to test_programs/execution_success/traits_in_crates_2/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/tuple_inputs/Nargo.toml b/test_programs/execution_success/tuple_inputs/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/tuple_inputs/Nargo.toml rename to test_programs/execution_success/tuple_inputs/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/tuple_inputs/Prover.toml b/test_programs/execution_success/tuple_inputs/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/tuple_inputs/Prover.toml rename to test_programs/execution_success/tuple_inputs/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/tuple_inputs/src/main.nr b/test_programs/execution_success/tuple_inputs/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/tuple_inputs/src/main.nr rename to test_programs/execution_success/tuple_inputs/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/tuples/Nargo.toml b/test_programs/execution_success/tuples/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/tuples/Nargo.toml rename to test_programs/execution_success/tuples/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/tuples/Prover.toml b/test_programs/execution_success/tuples/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/tuples/Prover.toml rename to test_programs/execution_success/tuples/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/tuples/src/main.nr b/test_programs/execution_success/tuples/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/tuples/src/main.nr rename to test_programs/execution_success/tuples/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/type_aliases/Nargo.toml b/test_programs/execution_success/type_aliases/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/type_aliases/Nargo.toml rename to test_programs/execution_success/type_aliases/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/type_aliases/Prover.toml b/test_programs/execution_success/type_aliases/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/type_aliases/Prover.toml rename to test_programs/execution_success/type_aliases/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/type_aliases/src/main.nr b/test_programs/execution_success/type_aliases/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/type_aliases/src/main.nr rename to test_programs/execution_success/type_aliases/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/workspace/Nargo.toml b/test_programs/execution_success/workspace/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace/Nargo.toml rename to test_programs/execution_success/workspace/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/workspace/Prover.toml b/test_programs/execution_success/workspace/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace/Prover.toml rename to test_programs/execution_success/workspace/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/workspace/crates/a/Nargo.toml b/test_programs/execution_success/workspace/crates/a/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace/crates/a/Nargo.toml rename to test_programs/execution_success/workspace/crates/a/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/workspace/crates/a/Prover.toml b/test_programs/execution_success/workspace/crates/a/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace/crates/a/Prover.toml rename to test_programs/execution_success/workspace/crates/a/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/workspace_default_member/a/src/main.nr b/test_programs/execution_success/workspace/crates/a/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace_default_member/a/src/main.nr rename to test_programs/execution_success/workspace/crates/a/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/workspace/crates/b/Nargo.toml b/test_programs/execution_success/workspace/crates/b/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace/crates/b/Nargo.toml rename to test_programs/execution_success/workspace/crates/b/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/workspace/crates/b/Prover.toml b/test_programs/execution_success/workspace/crates/b/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace/crates/b/Prover.toml rename to test_programs/execution_success/workspace/crates/b/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/workspace/crates/b/src/main.nr b/test_programs/execution_success/workspace/crates/b/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace/crates/b/src/main.nr rename to test_programs/execution_success/workspace/crates/b/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/workspace_default_member/Nargo.toml b/test_programs/execution_success/workspace_default_member/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace_default_member/Nargo.toml rename to test_programs/execution_success/workspace_default_member/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/workspace_default_member/Prover.toml b/test_programs/execution_success/workspace_default_member/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace_default_member/Prover.toml rename to test_programs/execution_success/workspace_default_member/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/workspace_default_member/a/Nargo.toml b/test_programs/execution_success/workspace_default_member/a/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace_default_member/a/Nargo.toml rename to test_programs/execution_success/workspace_default_member/a/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/workspace_default_member/a/Prover.toml b/test_programs/execution_success/workspace_default_member/a/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace_default_member/a/Prover.toml rename to test_programs/execution_success/workspace_default_member/a/Prover.toml diff --git a/test_programs/execution_success/workspace_default_member/a/src/main.nr b/test_programs/execution_success/workspace_default_member/a/src/main.nr new file mode 100644 index 0000000000..cf72627da2 --- /dev/null +++ b/test_programs/execution_success/workspace_default_member/a/src/main.nr @@ -0,0 +1,3 @@ +fn main(x: Field, y: pub Field) { + assert(x == y); +} diff --git a/tooling/nargo_cli/tests/execution_success/workspace_default_member/b/Nargo.toml b/test_programs/execution_success/workspace_default_member/b/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace_default_member/b/Nargo.toml rename to test_programs/execution_success/workspace_default_member/b/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/workspace_default_member/b/Prover.toml b/test_programs/execution_success/workspace_default_member/b/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/workspace_default_member/b/Prover.toml rename to test_programs/execution_success/workspace_default_member/b/Prover.toml diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/b/src/main.nr b/test_programs/execution_success/workspace_default_member/b/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/b/src/main.nr rename to test_programs/execution_success/workspace_default_member/b/src/main.nr diff --git a/tooling/nargo_cli/tests/execution_success/xor/Nargo.toml b/test_programs/execution_success/xor/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/xor/Nargo.toml rename to test_programs/execution_success/xor/Nargo.toml diff --git a/tooling/nargo_cli/tests/execution_success/xor/Prover.toml b/test_programs/execution_success/xor/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/execution_success/xor/Prover.toml rename to test_programs/execution_success/xor/Prover.toml diff --git a/tooling/nargo_cli/tests/execution_success/xor/src/main.nr b/test_programs/execution_success/xor/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/execution_success/xor/src/main.nr rename to test_programs/execution_success/xor/src/main.nr diff --git a/tooling/nargo_cli/tests/gates_report.sh b/test_programs/gates_report.sh similarity index 100% rename from tooling/nargo_cli/tests/gates_report.sh rename to test_programs/gates_report.sh diff --git a/tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/Nargo.toml b/test_programs/noir_test_failure/should_fail_mismatch/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/Nargo.toml rename to test_programs/noir_test_failure/should_fail_mismatch/Nargo.toml diff --git a/tooling/nargo_cli/tests/test_libraries/bad_name/src/lib.nr b/test_programs/noir_test_failure/should_fail_mismatch/Prover.toml similarity index 100% rename from tooling/nargo_cli/tests/test_libraries/bad_name/src/lib.nr rename to test_programs/noir_test_failure/should_fail_mismatch/Prover.toml diff --git a/tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/src/main.nr b/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/src/main.nr rename to test_programs/noir_test_failure/should_fail_mismatch/src/main.nr diff --git a/tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/Nargo.toml b/test_programs/noir_test_success/should_fail_with_matches/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/Nargo.toml rename to test_programs/noir_test_success/should_fail_with_matches/Nargo.toml diff --git a/test_programs/noir_test_success/should_fail_with_matches/Prover.toml b/test_programs/noir_test_success/should_fail_with_matches/Prover.toml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/src/main.nr b/test_programs/noir_test_success/should_fail_with_matches/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/src/main.nr rename to test_programs/noir_test_success/should_fail_with_matches/src/main.nr diff --git a/test_programs/rebuild.sh b/test_programs/rebuild.sh new file mode 100755 index 0000000000..d879ca417e --- /dev/null +++ b/test_programs/rebuild.sh @@ -0,0 +1,62 @@ +#!/bin/bash +set -e + +process_dir() { + local dir=$1 + local current_dir=$2 + local dir_name=$(basename "$dir") + + if [[ ! -d "$current_dir/acir_artifacts/$dir_name" ]]; then + mkdir -p $current_dir/acir_artifacts/$dir_name + fi + + cd $dir + if [ -d ./target/ ]; then + rm -r ./target/ + fi + cargo run compile --only-acir && cargo run execute witness + + if [ -d "$current_dir/acir_artifacts/$dir_name/target" ]; then + rm -r "$current_dir/acir_artifacts/$dir_name/target" + fi + mkdir $current_dir/acir_artifacts/$dir_name/target + + mv ./target/*.gz $current_dir/acir_artifacts/$dir_name/target/ + + cd $current_dir +} + +export -f process_dir + +excluded_dirs=("workspace" "workspace_default_member") +current_dir=$(pwd) +base_path="$current_dir/execution_success" + +rm -rf $current_dir/acir_artifacts +mkdir -p $current_dir/acir_artifacts + +# Gather directories to process. +dirs_to_process=() +for dir in $base_path/*; do + if [[ ! -d $dir ]] || [[ " ${excluded_dirs[@]} " =~ " $(basename "$dir") " ]]; then + continue + fi + dirs_to_process+=("$dir") +done + +# Process each directory in parallel +pids=() +for dir in "${dirs_to_process[@]}"; do + process_dir "$dir" "$current_dir" & + pids+=($!) +done + +# Check the exit status of each background job. +for pid in "${pids[@]}"; do + wait $pid || exit_status=$? +done + +# Exit with a failure status if any job failed. +if [ ! -z "$exit_status" ]; then + exit $exit_status +fi \ No newline at end of file diff --git a/tooling/nargo_cli/tests/test_libraries/bad_impl/Nargo.toml b/test_programs/test_libraries/bad_impl/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/test_libraries/bad_impl/Nargo.toml rename to test_programs/test_libraries/bad_impl/Nargo.toml diff --git a/tooling/nargo_cli/tests/test_libraries/bad_impl/src/lib.nr b/test_programs/test_libraries/bad_impl/src/lib.nr similarity index 100% rename from tooling/nargo_cli/tests/test_libraries/bad_impl/src/lib.nr rename to test_programs/test_libraries/bad_impl/src/lib.nr diff --git a/tooling/nargo_cli/tests/test_libraries/bad_name/Nargo.toml b/test_programs/test_libraries/bad_name/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/test_libraries/bad_name/Nargo.toml rename to test_programs/test_libraries/bad_name/Nargo.toml diff --git a/test_programs/test_libraries/bad_name/src/lib.nr b/test_programs/test_libraries/bad_name/src/lib.nr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tooling/nargo_cli/tests/test_libraries/bin_dep/Nargo.toml b/test_programs/test_libraries/bin_dep/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/test_libraries/bin_dep/Nargo.toml rename to test_programs/test_libraries/bin_dep/Nargo.toml diff --git a/tooling/nargo_cli/tests/test_libraries/bin_dep/src/main.nr b/test_programs/test_libraries/bin_dep/src/main.nr similarity index 100% rename from tooling/nargo_cli/tests/test_libraries/bin_dep/src/main.nr rename to test_programs/test_libraries/bin_dep/src/main.nr diff --git a/tooling/nargo_cli/tests/test_libraries/diamond_deps_1/Nargo.toml b/test_programs/test_libraries/diamond_deps_1/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/test_libraries/diamond_deps_1/Nargo.toml rename to test_programs/test_libraries/diamond_deps_1/Nargo.toml diff --git a/tooling/nargo_cli/tests/test_libraries/diamond_deps_1/src/lib.nr b/test_programs/test_libraries/diamond_deps_1/src/lib.nr similarity index 100% rename from tooling/nargo_cli/tests/test_libraries/diamond_deps_1/src/lib.nr rename to test_programs/test_libraries/diamond_deps_1/src/lib.nr diff --git a/tooling/nargo_cli/tests/test_libraries/diamond_deps_2/Nargo.toml b/test_programs/test_libraries/diamond_deps_2/Nargo.toml similarity index 100% rename from tooling/nargo_cli/tests/test_libraries/diamond_deps_2/Nargo.toml rename to test_programs/test_libraries/diamond_deps_2/Nargo.toml diff --git a/tooling/nargo_cli/tests/test_libraries/diamond_deps_2/src/lib.nr b/test_programs/test_libraries/diamond_deps_2/src/lib.nr similarity index 100% rename from tooling/nargo_cli/tests/test_libraries/diamond_deps_2/src/lib.nr rename to test_programs/test_libraries/diamond_deps_2/src/lib.nr diff --git a/tooling/backend_interface/Cargo.toml b/tooling/backend_interface/Cargo.toml index 14b1609dd4..a9217af65d 100644 --- a/tooling/backend_interface/Cargo.toml +++ b/tooling/backend_interface/Cargo.toml @@ -16,6 +16,7 @@ thiserror.workspace = true serde.workspace = true serde_json.workspace = true bb_abstraction_leaks.workspace = true +log.workspace = true tempfile = "3.6.0" diff --git a/tooling/backend_interface/src/lib.rs b/tooling/backend_interface/src/lib.rs index 6c91c181a9..d25319e11d 100644 --- a/tooling/backend_interface/src/lib.rs +++ b/tooling/backend_interface/src/lib.rs @@ -116,7 +116,7 @@ impl Backend { // If version doesn't match then download the correct version. Ok(version_string) => { - println!("`{ACVM_BACKEND_BARRETENBERG}` version `{version_string}` is different from expected `{BB_VERSION}`. Downloading expected version..."); + log::warn!("`{ACVM_BACKEND_BARRETENBERG}` version `{version_string}` is different from expected `{BB_VERSION}`. Downloading expected version..."); let bb_url = std::env::var("BB_BINARY_URL") .unwrap_or_else(|_| bb_abstraction_leaks::BB_DOWNLOAD_URL.to_owned()); download_backend(&bb_url, binary_path)?; @@ -124,7 +124,7 @@ impl Backend { // If `bb` fails to report its version, then attempt to fix it by re-downloading the binary. Err(_) => { - println!("Could not determine version of `{ACVM_BACKEND_BARRETENBERG}`. Downloading expected version..."); + log::warn!("Could not determine version of `{ACVM_BACKEND_BARRETENBERG}`. Downloading expected version..."); let bb_url = std::env::var("BB_BINARY_URL") .unwrap_or_else(|_| bb_abstraction_leaks::BB_DOWNLOAD_URL.to_owned()); download_backend(&bb_url, binary_path)?; @@ -153,6 +153,34 @@ impl BackendOpcodeSupport { } } } + + pub fn all() -> BackendOpcodeSupport { + BackendOpcodeSupport { + opcodes: HashSet::from([ + "arithmetic".to_string(), + "directive".to_string(), + "brillig".to_string(), + "memory_init".to_string(), + "memory_op".to_string(), + ]), + black_box_functions: HashSet::from([ + "sha256".to_string(), + "schnorr_verify".to_string(), + "blake2s".to_string(), + "pedersen".to_string(), + "pedersen_hash".to_string(), + "hash_to_field_128_security".to_string(), + "ecdsa_secp256k1".to_string(), + "fixed_base_scalar_mul".to_string(), + "and".to_string(), + "xor".to_string(), + "range".to_string(), + "keccak256".to_string(), + "recursive_aggregation".to_string(), + "ecdsa_secp256r1".to_string(), + ]), + } + } } #[cfg(test)] diff --git a/tooling/backend_interface/src/proof_system.rs b/tooling/backend_interface/src/proof_system.rs index 95da1462d4..bb47603bbf 100644 --- a/tooling/backend_interface/src/proof_system.rs +++ b/tooling/backend_interface/src/proof_system.rs @@ -36,6 +36,18 @@ impl Backend { InfoCommand { crs_path: self.crs_directory() }.run(binary_path) } + /// If we cannot get a valid backend, returns the default backend which supports all the opcodes + /// and uses Plonk with width 3 + /// The function also prints a message saying we could not find a backend + pub fn get_backend_info_or_default(&self) -> (Language, BackendOpcodeSupport) { + if let Ok(backend_info) = self.get_backend_info() { + (backend_info.0, backend_info.1) + } else { + log::warn!("No valid backend found, defaulting to Plonk with width 3 and all opcodes supported"); + (Language::PLONKCSat { width: 3 }, BackendOpcodeSupport::all()) + } + } + pub fn prove( &self, circuit: &Circuit, diff --git a/tooling/bb_abstraction_leaks/build.rs b/tooling/bb_abstraction_leaks/build.rs index fe6861a80b..166e61a5a9 100644 --- a/tooling/bb_abstraction_leaks/build.rs +++ b/tooling/bb_abstraction_leaks/build.rs @@ -10,7 +10,7 @@ use const_format::formatcp; const USERNAME: &str = "AztecProtocol"; const REPO: &str = "aztec-packages"; -const VERSION: &str = "0.12.0"; +const VERSION: &str = "0.16.0"; const TAG: &str = formatcp!("aztec-packages-v{}", VERSION); const API_URL: &str = @@ -30,8 +30,11 @@ fn main() -> Result<(), String> { }; // Arm builds of linux are not supported + // We do not panic because we allow users to run nargo without a backend. if let (Os::Linux, Arch::AARCH64) = (&os, &arch) { - panic!("ARM64 builds of linux are not supported") + println!( + "cargo:warning=ARM64 builds of linux are not supported for the barretenberg binary" + ); }; println!("cargo:rustc-env=BB_BINARY_URL={}", get_bb_download_url(arch, os)); diff --git a/tooling/debugger/README.md b/tooling/debugger/README.md new file mode 100644 index 0000000000..964784cb73 --- /dev/null +++ b/tooling/debugger/README.md @@ -0,0 +1,348 @@ +# Noir Debugger + +There are currently two ways of debugging Noir programs, both in active development and in experimental phase: + +1. The REPL debugger, which currently ships with Nargo behind a feature flag. +2. The VS Code extension, which hasn't still reached minimum viability, and so must be manually set up. + +This README explains how to use each of them as well as specifying which features are currently mature and which ones are unstable. + +## Supported project types + +At the time of writing, the debugger supports debugging binary projects, but not contracts. At the end of this README, we'll elaborate on what the current state of Noir contract debugging is, and the pre-requisites to fulfil. + + +## REPL debugger + +In order to use the REPL debugger, you will need to install a new enough version of Nargo. At the time of writing, the nightly version is 0.20.0, so we'll base this guide on it. + +Let's debug a simple circuit: + +``` +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then: + +`$ nargo debug` + +You should be seeing this in your terminal: + +``` +[main] Starting debugger +At opcode 0: EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] +At ~/noir-examples/recursion/circuits/main/src/main.nr:2:12 + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> +``` + +The debugger displays the current opcode, and the corresponding Noir code location associated to it, and it is now waiting for us to drive it. + +Let's first take a look at the available commands. For that we'll use the `help` command. + +``` +At ~/noir-examples/recursion/circuits/main/src/main.nr:2:12 + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> help +Available commands: + + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + memory show Brillig memory (valid when executing a + Brillig block) + into step into to the next opcode + next step until a new source location is reached + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + step step to the next ACIR opcode + registers show Brillig registers (valid when executing + a Brillig block) + regset index:usize value:String update a Brillig register with the given + value + restart restart the debugging session + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + continue continue execution until the end of the + program + opcodes display ACIR opcodes + memset index:usize value:String update a Brillig memory cell with the given + value + +Other commands: + + help Show this help message + quit Quit repl +``` + +The command menu is pretty self-explanatory. Some commands operate only at Brillig level, such as `memory`, `memset`, `registers`, `regset`. If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing Brillig code: + +``` +> registers +Not executing a Brillig block +> +``` + +Before continuing, we can take a look at the initial witness map: + +``` +> witness +_1 = 1 +_2 = 2 +> +``` + +Cool, since `x==1`, `y==2`, and we want to check that `x != y`, our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set `y=3`, then back to 2: + +``` +> witness +_1 = 1 +_2 = 2 +> witness 2 3 +_2 = 3 +> witness +_1 = 1 +_2 = 3 +> witness 2 2 +_2 = 2 +> witness +_1 = 1 +_2 = 2 +> +``` + +Let's take a look at this circuit's ACIR, using the `opcodes` command: + +``` +> opcodes + 0 -> EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 | JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> +``` + +Note: in future versions of the debugger, we could explore prettier or more compact formats to print opcodes. + +So the next opcode will take us to Brillig execution. Let's step into opcode 1 so we can explore Brillig debugger commands. + +``` +> into +At opcode 1: BRILLIG: inputs: [Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] +outputs: [Simple(Witness(4))] +[JumpIfNot { condition: RegisterIndex(0), location: 3 }, Const { destination: RegisterIndex(1), value: Value { inner: 1 } }, BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) }, Stop] + +At /~/noir-examples/recursion/circuits/main/src/main.nr:2:12 + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +``` + +In disassembly view: + +``` +> op + 0 EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 |-> JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> witness +_1 = 1 +_2 = 2 +_3 = 1 +> +``` + +We can see two arrow `->` cursors: one indicates where we are from the perspective of ACIR (opcode 1), and the other one shows us where we are in the context of the current Brillig block (opcode 1.0). + +Note: REPL commands are autocompleted when not ambiguous, so `opcodes` can be run just with `op`, `into` with `i`, etc. + +The next opcode to execute is a `JumpIfNot`, which reads from register 0. Let's inspect Brillig register state: + +``` +> op + 0 EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 |-> JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> registers +Brillig VM registers not available +``` + +Oops. This is unexpected, even though we were already in a Brillig block, we couldn't access the Brillig registers. This is a known issue: when just entering the Brillig block, the ACVM has not yet initialized the Brillig VM, so we can't introspect it. + +Note: In order to solve this, we would have to change the way the ACVM works, or add special handling for this case (after all, the debugger does know we're at the first opcode of a Brillig block and could keep track of how registers will be initialized). At the time of writing, we haven't yet solved this case. + +For now, let's just step once more: + +``` +> i +At opcode 1.1: Const { destination: RegisterIndex(1), value: Value { inner: 1 } } +> registers +0 = 1 +> +``` + +Now we can see that register 0 was initialized with a value of 1, so the `JumpIfNot` didn't activate. After executing opcode 1, we should see register 1 gets a value of 1: + +``` +> i +At opcode 1.2: BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } +> regist +0 = 1 +1 = 1 +> +``` + +The last operation will compute `Reg0 <- Reg1 / Reg0`: + +``` +> i +At opcode 1.3: Stop +> registers +0 = 1 +1 = 1 +> +``` + +Once we step again, we'll be out of Brillig and back on ACVM territory. With a new witness `_4` corresponding to the result of the Brillig block execution: + +``` +> op + 0 EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 | JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 -> EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> wit +_1 = 1 +_2 = 2 +_3 = 1 +_4 = 1 +> +``` + +At any time, we might also decide to restart from the beginning: + +``` +> restart +Restarted debugging session. +At opcode 0: EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] +At ~/noir-examples/recursion/circuits/main/src/main.nr:2:12 + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> +``` + +Let's set a breakpoint. For that, we can use the opcode id's listed by the `opcodes` command: + +``` +> opcodes + 0 -> EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 | JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 | BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> break 1.2 +Added breakpoint at opcode 1.2 +``` + +Now we can have the debugger continue all the way to opcode 1.2: + +``` +> break 1.2 +Added breakpoint at opcode 1.2 +> continue +(Continuing execution...) +Stopped at breakpoint in opcode 1.2 +At opcode 1.2: BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } +> opcodes + 0 EXPR [ (-1, _1) (1, _2) (-1, _3) 0 ] + 1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(3))], q_c: 0 })] + | outputs=[Simple(Witness(4))] + 1.0 | JumpIfNot { condition: RegisterIndex(0), location: 3 } + 1.1 | Const { destination: RegisterIndex(1), value: Value { inner: 1 } } + 1.2 |-> BinaryFieldOp { destination: RegisterIndex(0), op: Div, lhs: RegisterIndex(1), rhs: RegisterIndex(0) } + 1.3 | Stop + 2 EXPR [ (1, _3, _4) (1, _5) -1 ] + 3 EXPR [ (1, _3, _5) 0 ] + 4 EXPR [ (-1, _5) 0 ] +> +``` + +Let's continue to the end: + +``` +> continue +(Continuing execution...) +Finished execution +> q +[main] Circuit witness successfully solved +``` + +Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`. + +## VS Code extension + +We're working on extending Noir's official VS Code extension so it uses the editor's debugger facilities to debug Noir programs. + +This section will soon show how to load the extension from sources, in order to test the debugger. + + +## Variable value inspection (unstable) + +To enable the inspection of variable values at runtime from the debugger, we're in the process of instrumenting the compiler to track and collect the necessary mappings between source code level variable names and ACIR/Brillig state. + +At the time of writing, there are still some parts of the language that haven't been fully instrumented, which means certain programs will crash when compiled with this. + +It is however possible to try out this feature, both from the REPL and VS Code, by building Nargo from branch https://github.com/manastech/noir/tree/dap-with-vars. + +We'll soon expand this section with details on how to do so for the adventurous. + + +## Towards debugging contracts + +### Contracts Runtime + +The execution of Noir contracts depends on a foreign call execution runtime to resolve all the oracle calls that the contract functions depend on. + +This means for the debugger to be usable with contracts we need to be able to do at least one of the following: + +1. Let users mock out a foreign call executor, and run the debugger with it. +2. Instrument live environments, such as the Sandbox, so that calls and transactions can be driven by the debugger, which ultimately means the debugger would use the same foreign call executor a live Sandbox uses for normal execution of Noir circuits. + +Both of these scenarios imply making the debugger available to language runtimes external to Noir. The Sandbox/PXE runs on JS runtimes, and an hypothetical mockable foreign executor could be in principle written in any language. So it seems the most promising way forward is to make sure that the debugger itself is consumable in JS runtimes. + diff --git a/tooling/debugger/src/context.rs b/tooling/debugger/src/context.rs index 33862ed641..1475827fbe 100644 --- a/tooling/debugger/src/context.rs +++ b/tooling/debugger/src/context.rs @@ -8,7 +8,7 @@ use acvm::{BlackBoxFunctionSolver, FieldElement}; use nargo::artifacts::debug::DebugArtifact; use nargo::errors::{ExecutionError, Location}; -use nargo::ops::{DefaultForeignCallExecutor, ForeignCallExecutor}; +use nargo::ops::ForeignCallExecutor; use nargo::NargoError; use std::collections::{hash_set::Iter, HashSet}; @@ -24,7 +24,7 @@ pub(super) enum DebugCommandResult { pub(super) struct DebugContext<'a, B: BlackBoxFunctionSolver> { acvm: ACVM<'a, B>, brillig_solver: Option>, - foreign_call_executor: DefaultForeignCallExecutor, + foreign_call_executor: Box, debug_artifact: &'a DebugArtifact, breakpoints: HashSet, } @@ -35,11 +35,12 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { circuit: &'a Circuit, debug_artifact: &'a DebugArtifact, initial_witness: WitnessMap, + foreign_call_executor: Box, ) -> Self { Self { acvm: ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness), brillig_solver: None, - foreign_call_executor: DefaultForeignCallExecutor::new(true), + foreign_call_executor, debug_artifact, breakpoints: HashSet::new(), } @@ -120,7 +121,12 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { let foreign_call_result = self.foreign_call_executor.execute(&foreign_call); match foreign_call_result { Ok(foreign_call_result) => { - self.acvm.resolve_pending_foreign_call(foreign_call_result); + if let Some(mut solver) = self.brillig_solver.take() { + solver.resolve_pending_foreign_call(foreign_call_result); + self.brillig_solver = Some(solver); + } else { + self.acvm.resolve_pending_foreign_call(foreign_call_result); + } // TODO: should we retry executing the opcode somehow in this case? DebugCommandResult::Ok } @@ -168,13 +174,50 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { } } + fn currently_executing_brillig(&self) -> bool { + if self.brillig_solver.is_some() { + return true; + } + + match self.get_current_opcode_location() { + Some(OpcodeLocation::Brillig { .. }) => true, + Some(OpcodeLocation::Acir(acir_index)) => { + matches!(self.get_opcodes()[acir_index], Opcode::Brillig(_)) + } + _ => false, + } + } + + fn get_current_acir_index(&self) -> Option { + self.get_current_opcode_location().map(|opcode_location| match opcode_location { + OpcodeLocation::Acir(acir_index) => acir_index, + OpcodeLocation::Brillig { acir_index, .. } => acir_index, + }) + } + + fn step_out_of_brillig_opcode(&mut self) -> DebugCommandResult { + let Some(start_acir_index) = self.get_current_acir_index() else { + return DebugCommandResult::Done; + }; + loop { + let result = self.step_into_opcode(); + if !matches!(result, DebugCommandResult::Ok) { + return result; + } + let new_acir_index = self.get_current_acir_index().unwrap(); + if new_acir_index != start_acir_index { + return DebugCommandResult::Ok; + } + } + } + pub(super) fn step_acir_opcode(&mut self) -> DebugCommandResult { - let status = if let Some(solver) = self.brillig_solver.take() { - self.acvm.finish_brillig_with_solver(solver) + if self.currently_executing_brillig() { + self.step_out_of_brillig_opcode() } else { - self.acvm.solve_opcode() - }; - self.handle_acvm_status(status) + let status = self.acvm.solve_opcode(); + self.handle_acvm_status(status) + } } pub(super) fn next(&mut self) -> DebugCommandResult { @@ -276,3 +319,220 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { self.acvm.finalize() } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::context::{DebugCommandResult, DebugContext}; + + use acvm::{ + acir::{ + circuit::brillig::{Brillig, BrilligInputs, BrilligOutputs}, + native_types::Expression, + }, + brillig_vm::brillig::{ + BinaryFieldOp, Opcode as BrilligOpcode, RegisterIndex, RegisterOrMemory, + }, + }; + use nargo::{artifacts::debug::DebugArtifact, ops::DefaultForeignCallExecutor}; + use std::collections::BTreeMap; + + struct StubbedSolver; + + impl BlackBoxFunctionSolver for StubbedSolver { + fn schnorr_verify( + &self, + _public_key_x: &FieldElement, + _public_key_y: &FieldElement, + _signature: &[u8], + _message: &[u8], + ) -> Result { + unimplemented!(); + } + + fn pedersen_commitment( + &self, + _inputs: &[FieldElement], + _domain_separator: u32, + ) -> Result<(FieldElement, FieldElement), acvm::BlackBoxResolutionError> { + unimplemented!(); + } + + fn pedersen_hash( + &self, + _inputs: &[FieldElement], + _domain_separator: u32, + ) -> Result { + unimplemented!(); + } + + fn fixed_base_scalar_mul( + &self, + _low: &FieldElement, + _high: &FieldElement, + ) -> Result<(FieldElement, FieldElement), acvm::BlackBoxResolutionError> { + unimplemented!(); + } + } + + #[test] + fn test_resolve_foreign_calls_stepping_into_brillig() { + let fe_0 = FieldElement::zero(); + let fe_1 = FieldElement::one(); + let w_x = Witness(1); + + let blackbox_solver = &StubbedSolver; + + let brillig_opcodes = Brillig { + inputs: vec![BrilligInputs::Single(Expression { + linear_combinations: vec![(fe_1, w_x)], + ..Expression::default() + })], + outputs: vec![], + bytecode: vec![ + BrilligOpcode::Const { + destination: RegisterIndex::from(1), + value: Value::from(fe_0), + }, + BrilligOpcode::ForeignCall { + function: "clear_mock".into(), + destinations: vec![], + inputs: vec![RegisterOrMemory::RegisterIndex(RegisterIndex::from(0))], + }, + BrilligOpcode::Stop, + ], + predicate: None, + }; + let opcodes = vec![Opcode::Brillig(brillig_opcodes)]; + let current_witness_index = 2; + let circuit = &Circuit { current_witness_index, opcodes, ..Circuit::default() }; + + let debug_symbols = vec![]; + let file_map = BTreeMap::new(); + let warnings = vec![]; + let debug_artifact = &DebugArtifact { debug_symbols, file_map, warnings }; + + let initial_witness = BTreeMap::from([(Witness(1), fe_1)]).into(); + + let mut context = DebugContext::new( + blackbox_solver, + circuit, + debug_artifact, + initial_witness, + Box::new(DefaultForeignCallExecutor::new(true)), + ); + + assert_eq!(context.get_current_opcode_location(), Some(OpcodeLocation::Acir(0))); + + // execute the first Brillig opcode (const) + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_opcode_location(), + Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }) + ); + + // try to execute the second Brillig opcode (and resolve the foreign call) + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_opcode_location(), + Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }) + ); + + // retry the second Brillig opcode (foreign call should be finished) + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!( + context.get_current_opcode_location(), + Some(OpcodeLocation::Brillig { acir_index: 0, brillig_index: 2 }) + ); + + // last Brillig opcode + let result = context.step_into_opcode(); + assert!(matches!(result, DebugCommandResult::Done)); + assert_eq!(context.get_current_opcode_location(), None); + } + + #[test] + fn test_break_brillig_block_while_stepping_acir_opcodes() { + let fe_0 = FieldElement::zero(); + let fe_1 = FieldElement::one(); + let w_x = Witness(1); + let w_y = Witness(2); + let w_z = Witness(3); + + let blackbox_solver = &StubbedSolver; + + // This Brillig block is equivalent to: z = x + y + let brillig_opcodes = Brillig { + inputs: vec![ + BrilligInputs::Single(Expression { + linear_combinations: vec![(fe_1, w_x)], + ..Expression::default() + }), + BrilligInputs::Single(Expression { + linear_combinations: vec![(fe_1, w_y)], + ..Expression::default() + }), + ], + outputs: vec![BrilligOutputs::Simple(w_z)], + bytecode: vec![ + BrilligOpcode::BinaryFieldOp { + destination: RegisterIndex::from(0), + op: BinaryFieldOp::Add, + lhs: RegisterIndex::from(0), + rhs: RegisterIndex::from(1), + }, + BrilligOpcode::Stop, + ], + predicate: None, + }; + let opcodes = vec![ + // z = x + y + Opcode::Brillig(brillig_opcodes), + // x + y - z = 0 + Opcode::Arithmetic(Expression { + mul_terms: vec![], + linear_combinations: vec![(fe_1, w_x), (fe_1, w_y), (-fe_1, w_z)], + q_c: fe_0, + }), + ]; + let current_witness_index = 3; + let circuit = &Circuit { current_witness_index, opcodes, ..Circuit::default() }; + + let debug_symbols = vec![]; + let file_map = BTreeMap::new(); + let warnings = vec![]; + let debug_artifact = &DebugArtifact { debug_symbols, file_map, warnings }; + + let initial_witness = BTreeMap::from([(Witness(1), fe_1), (Witness(2), fe_1)]).into(); + + let mut context = DebugContext::new( + blackbox_solver, + circuit, + debug_artifact, + initial_witness, + Box::new(DefaultForeignCallExecutor::new(true)), + ); + + // set breakpoint + let breakpoint_location = OpcodeLocation::Brillig { acir_index: 0, brillig_index: 1 }; + assert!(context.add_breakpoint(breakpoint_location)); + + // execute the first ACIR opcode (Brillig block) -> should reach the breakpoint instead + let result = context.step_acir_opcode(); + assert!(matches!(result, DebugCommandResult::BreakpointReached(_))); + assert_eq!(context.get_current_opcode_location(), Some(breakpoint_location)); + + // continue execution to the next ACIR opcode + let result = context.step_acir_opcode(); + assert!(matches!(result, DebugCommandResult::Ok)); + assert_eq!(context.get_current_opcode_location(), Some(OpcodeLocation::Acir(1))); + + // last ACIR opcode + let result = context.step_acir_opcode(); + assert!(matches!(result, DebugCommandResult::Done)); + assert_eq!(context.get_current_opcode_location(), None); + } +} diff --git a/tooling/debugger/src/repl.rs b/tooling/debugger/src/repl.rs index 23abe83c38..cb6539cbdb 100644 --- a/tooling/debugger/src/repl.rs +++ b/tooling/debugger/src/repl.rs @@ -4,8 +4,7 @@ use acvm::acir::circuit::{Circuit, Opcode, OpcodeLocation}; use acvm::acir::native_types::{Witness, WitnessMap}; use acvm::{BlackBoxFunctionSolver, FieldElement}; -use nargo::artifacts::debug::DebugArtifact; -use nargo::NargoError; +use nargo::{artifacts::debug::DebugArtifact, ops::DefaultForeignCallExecutor, NargoError}; use easy_repl::{command, CommandStatus, Repl}; use std::cell::RefCell; @@ -33,8 +32,13 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { debug_artifact: &'a DebugArtifact, initial_witness: WitnessMap, ) -> Self { - let context = - DebugContext::new(blackbox_solver, circuit, debug_artifact, initial_witness.clone()); + let context = DebugContext::new( + blackbox_solver, + circuit, + debug_artifact, + initial_witness.clone(), + Box::new(DefaultForeignCallExecutor::new(true)), + ); Self { context, blackbox_solver, @@ -274,6 +278,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { self.circuit, self.debug_artifact, self.initial_witness.clone(), + Box::new(DefaultForeignCallExecutor::new(true)), ); for opcode_location in breakpoints { self.context.add_breakpoint(opcode_location); diff --git a/tooling/lsp/Cargo.toml b/tooling/lsp/Cargo.toml index 9e642d5fe9..5f5e701da6 100644 --- a/tooling/lsp/Cargo.toml +++ b/tooling/lsp/Cargo.toml @@ -11,9 +11,9 @@ license.workspace = true [dependencies] acvm.workspace = true codespan-lsp.workspace = true -codespan-reporting.workspace = true lsp-types.workspace = true nargo.workspace = true +nargo_fmt.workspace = true nargo_toml.workspace = true noirc_driver.workspace = true noirc_errors.workspace = true @@ -21,7 +21,6 @@ noirc_frontend.workspace = true serde.workspace = true serde_json.workspace = true tower.workspace = true -cfg-if.workspace = true async-lsp = { workspace = true, features = ["omni-trait"] } serde_with = "3.2.0" fm.workspace = true diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index 79fc544692..2ad8096a13 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -4,9 +4,10 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] use std::{ + collections::HashMap, future::Future, ops::{self, ControlFlow}, - path::{Path, PathBuf}, + path::PathBuf, pin::Pin, task::{self, Poll}, }; @@ -16,7 +17,7 @@ use async_lsp::{ router::Router, AnyEvent, AnyNotification, AnyRequest, ClientSocket, Error, LspService, ResponseError, }; -use codespan_reporting::files; +use fm::codespan_files as files; use noirc_frontend::{ graph::{CrateId, CrateName}, hir::{Context, FunctionNameMatch}, @@ -26,8 +27,8 @@ use notifications::{ on_did_open_text_document, on_did_save_text_document, on_exit, on_initialized, }; use requests::{ - on_code_lens_request, on_initialize, on_profile_run_request, on_shutdown, on_test_run_request, - on_tests_request, + on_formatting, on_goto_definition_request, on_initialize, on_profile_run_request, on_shutdown, + on_test_run_request, on_tests_request, }; use serde_json::Value as JsonValue; use tower::Service; @@ -45,11 +46,17 @@ pub struct LspState { root_path: Option, client: ClientSocket, solver: WrapperSolver, + input_files: HashMap, } impl LspState { fn new(client: &ClientSocket, solver: impl BlackBoxFunctionSolver + 'static) -> Self { - Self { client: client.clone(), root_path: None, solver: WrapperSolver(Box::new(solver)) } + Self { + client: client.clone(), + root_path: None, + solver: WrapperSolver(Box::new(solver)), + input_files: HashMap::new(), + } } } @@ -63,11 +70,12 @@ impl NargoLspService { let mut router = Router::new(state); router .request::(on_initialize) + .request::(on_formatting) .request::(on_shutdown) - .request::(on_code_lens_request) .request::(on_tests_request) .request::(on_test_run_request) .request::(on_profile_run_request) + .request::(on_goto_definition_request) .notification::(on_initialized) .notification::(on_did_change_configuration) .notification::(on_did_open_text_document) @@ -167,29 +175,3 @@ fn byte_span_to_range<'a, F: files::Files<'a> + ?Sized>( None } } - -cfg_if::cfg_if! { - if #[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))] { - use wasm_bindgen::{prelude::*, JsValue}; - - #[wasm_bindgen(module = "@noir-lang/source-resolver")] - extern "C" { - - #[wasm_bindgen(catch)] - fn read_file(path: &str) -> Result; - - } - - fn get_non_stdlib_asset(path_to_file: &Path) -> std::io::Result { - let path_str = path_to_file.to_str().unwrap(); - match read_file(path_str) { - Ok(buffer) => Ok(buffer), - Err(_) => Err(Error::new(ErrorKind::Other, "could not read file using wasm")), - } - } - } else { - fn get_non_stdlib_asset(path_to_file: &Path) -> std::io::Result { - std::fs::read_to_string(path_to_file) - } - } -} diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs index 93fa8baf6a..61f0d23173 100644 --- a/tooling/lsp/src/notifications/mod.rs +++ b/tooling/lsp/src/notifications/mod.rs @@ -2,7 +2,7 @@ use std::ops::ControlFlow; use async_lsp::{ErrorCode, LanguageClient, ResponseError}; use nargo::prepare_package; -use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use nargo_toml::{find_file_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::{check_crate, NOIR_ARTIFACT_VERSION_STRING}; use noirc_errors::{DiagnosticKind, FileDiagnostic}; @@ -13,7 +13,7 @@ use crate::types::{ PublishDiagnosticsParams, }; -use crate::{byte_span_to_range, get_non_stdlib_asset, get_package_tests_in_crate, LspState}; +use crate::{byte_span_to_range, get_package_tests_in_crate, LspState}; pub(super) fn on_initialized( _state: &mut LspState, @@ -30,23 +30,27 @@ pub(super) fn on_did_change_configuration( } pub(super) fn on_did_open_text_document( - _state: &mut LspState, - _params: DidOpenTextDocumentParams, + state: &mut LspState, + params: DidOpenTextDocumentParams, ) -> ControlFlow> { + state.input_files.insert(params.text_document.uri.to_string(), params.text_document.text); ControlFlow::Continue(()) } pub(super) fn on_did_change_text_document( - _state: &mut LspState, - _params: DidChangeTextDocumentParams, + state: &mut LspState, + params: DidChangeTextDocumentParams, ) -> ControlFlow> { + let text = params.content_changes.into_iter().next().unwrap().text; + state.input_files.insert(params.text_document.uri.to_string(), text); ControlFlow::Continue(()) } pub(super) fn on_did_close_text_document( - _state: &mut LspState, - _params: DidCloseTextDocumentParams, + state: &mut LspState, + params: DidCloseTextDocumentParams, ) -> ControlFlow> { + state.input_files.remove(¶ms.text_document.uri.to_string()); ControlFlow::Continue(()) } @@ -65,29 +69,21 @@ pub(super) fn on_did_save_text_document( } }; - let root_path = match &state.root_path { - Some(root) => root, - None => { - return ControlFlow::Break(Err(ResponseError::new( - ErrorCode::REQUEST_FAILED, - "Could not find project root", - ) - .into())); - } - }; + let package_root = find_file_manifest(file_path.as_path()); - let toml_path = match find_package_manifest(root_path, &file_path) { - Ok(toml_path) => toml_path, - Err(err) => { + let toml_path = match package_root { + Some(toml_path) => toml_path, + None => { // If we cannot find a manifest, we log a warning but return no diagnostics // We can reconsider this when we can build a file without the need for a Nargo.toml file to resolve deps let _ = state.client.log_message(LogMessageParams { typ: MessageType::WARNING, - message: format!("{err}"), + message: format!("Nargo.toml not found for file: {:}", file_path.display()), }); return ControlFlow::Continue(()); } }; + let workspace = match resolve_workspace_from_toml( &toml_path, PackageSelection::All, @@ -107,9 +103,9 @@ pub(super) fn on_did_save_text_document( let diagnostics: Vec<_> = workspace .into_iter() .flat_map(|package| -> Vec { - let (mut context, crate_id) = prepare_package(package, Box::new(get_non_stdlib_asset)); + let (mut context, crate_id) = prepare_package(package); - let file_diagnostics = match check_crate(&mut context, crate_id, false) { + let file_diagnostics = match check_crate(&mut context, crate_id, false, false) { Ok(((), warnings)) => warnings, Err(errors_and_warnings) => errors_and_warnings, }; @@ -157,9 +153,6 @@ pub(super) fn on_did_save_text_document( }) .collect(); - // We need to refresh lenses when we compile since that's the only time they can be accurately reflected - std::mem::drop(state.client.code_lens_refresh(())); - let _ = state.client.publish_diagnostics(PublishDiagnosticsParams { uri: params.text_document.uri, version: None, diff --git a/tooling/lsp/src/requests/code_lens_request.rs b/tooling/lsp/src/requests/code_lens_request.rs deleted file mode 100644 index 602ed26898..0000000000 --- a/tooling/lsp/src/requests/code_lens_request.rs +++ /dev/null @@ -1,235 +0,0 @@ -use std::future::{self, Future}; - -use async_lsp::{ErrorCode, LanguageClient, ResponseError}; - -use nargo::{package::Package, prepare_package, workspace::Workspace}; -use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{check_crate, NOIR_ARTIFACT_VERSION_STRING}; -use noirc_frontend::hir::FunctionNameMatch; - -use crate::{ - byte_span_to_range, get_non_stdlib_asset, - types::{CodeLens, CodeLensParams, CodeLensResult, Command, LogMessageParams, MessageType}, - LspState, -}; - -const ARROW: &str = "▶\u{fe0e}"; -const TEST_COMMAND: &str = "nargo.test"; -const TEST_CODELENS_TITLE: &str = "Run Test"; -const COMPILE_COMMAND: &str = "nargo.compile"; -const COMPILE_CODELENS_TITLE: &str = "Compile"; -const INFO_COMMAND: &str = "nargo.info"; -const INFO_CODELENS_TITLE: &str = "Info"; -const EXECUTE_COMMAND: &str = "nargo.execute"; -const EXECUTE_CODELENS_TITLE: &str = "Execute"; - -const PROFILE_COMMAND: &str = "nargo.profile"; -const PROFILE_CODELENS_TITLE: &str = "Profile"; - -fn with_arrow(title: &str) -> String { - format!("{ARROW} {title}") -} - -fn package_selection_args(workspace: &Workspace, package: &Package) -> Vec { - vec![ - "--program-dir".into(), - workspace.root_dir.display().to_string().into(), - "--package".into(), - package.name.to_string().into(), - ] -} - -pub(crate) fn on_code_lens_request( - state: &mut LspState, - params: CodeLensParams, -) -> impl Future> { - future::ready(on_code_lens_request_inner(state, params)) -} - -fn on_code_lens_request_inner( - state: &mut LspState, - params: CodeLensParams, -) -> Result { - let file_path = params.text_document.uri.to_file_path().map_err(|_| { - ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") - })?; - - let root_path = state.root_path.as_deref().ok_or_else(|| { - ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not find project root") - })?; - - let toml_path = match find_package_manifest(root_path, &file_path) { - Ok(toml_path) => toml_path, - Err(err) => { - // If we cannot find a manifest, we log a warning but return no code lenses - // We can reconsider this when we can build a file without the need for a Nargo.toml file to resolve deps - let _ = state.client.log_message(LogMessageParams { - typ: MessageType::WARNING, - message: err.to_string(), - }); - return Ok(None); - } - }; - let workspace = resolve_workspace_from_toml( - &toml_path, - PackageSelection::All, - Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), - ) - .map_err(|err| { - // If we found a manifest, but the workspace is invalid, we raise an error about it - ResponseError::new(ErrorCode::REQUEST_FAILED, err) - })?; - - let mut lenses: Vec = vec![]; - - for package in &workspace { - let (mut context, crate_id) = prepare_package(package, Box::new(get_non_stdlib_asset)); - // We ignore the warnings and errors produced by compilation for producing code lenses - // because we can still get the test functions even if compilation fails - let _ = check_crate(&mut context, crate_id, false); - - let fm = &context.file_manager; - let files = fm.as_file_map(); - let tests = context - .get_all_test_functions_in_crate_matching(&crate_id, FunctionNameMatch::Anything); - - for (func_name, test_function) in tests { - let location = context.function_meta(&test_function.get_id()).name.location; - let file_id = location.file; - - // Ignore diagnostics for any file that wasn't the file we saved - // TODO: In the future, we could create "related" diagnostics for these files - if fm.path(file_id) != file_path { - continue; - } - - let range = - byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); - - let test_command = Command { - title: with_arrow(TEST_CODELENS_TITLE), - command: TEST_COMMAND.into(), - arguments: Some( - [ - package_selection_args(&workspace, package), - vec!["--exact".into(), func_name.into()], - ] - .concat(), - ), - }; - - let test_lens = CodeLens { range, command: Some(test_command), data: None }; - - lenses.push(test_lens); - } - - if package.is_binary() { - if let Some(main_func_id) = context.get_main_function(&crate_id) { - let location = context.function_meta(&main_func_id).name.location; - let file_id = location.file; - - // Ignore diagnostics for any file that wasn't the file we saved - // TODO: In the future, we could create "related" diagnostics for these files - if fm.path(file_id) != file_path { - continue; - } - - let range = - byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); - - let compile_command = Command { - title: with_arrow(COMPILE_CODELENS_TITLE), - command: COMPILE_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let compile_lens = CodeLens { range, command: Some(compile_command), data: None }; - - lenses.push(compile_lens); - - let info_command = Command { - title: INFO_CODELENS_TITLE.to_string(), - command: INFO_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let info_lens = CodeLens { range, command: Some(info_command), data: None }; - - lenses.push(info_lens); - - let execute_command = Command { - title: EXECUTE_CODELENS_TITLE.to_string(), - command: EXECUTE_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let execute_lens = CodeLens { range, command: Some(execute_command), data: None }; - - lenses.push(execute_lens); - - let profile_command = Command { - title: PROFILE_CODELENS_TITLE.to_string(), - command: PROFILE_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let profile_lens = CodeLens { range, command: Some(profile_command), data: None }; - - lenses.push(profile_lens); - } - } - - if package.is_contract() { - // Currently not looking to deduplicate this since we don't have a clear decision on if the Contract stuff is staying - for contract in context.get_all_contracts(&crate_id) { - let location = contract.location; - let file_id = location.file; - - // Ignore diagnostics for any file that wasn't the file we saved - // TODO: In the future, we could create "related" diagnostics for these files - if fm.path(file_id) != file_path { - continue; - } - - let range = - byte_span_to_range(files, file_id, location.span.into()).unwrap_or_default(); - - let compile_command = Command { - title: with_arrow(COMPILE_CODELENS_TITLE), - command: COMPILE_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let compile_lens = CodeLens { range, command: Some(compile_command), data: None }; - - lenses.push(compile_lens); - - let info_command = Command { - title: INFO_CODELENS_TITLE.to_string(), - command: INFO_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let info_lens = CodeLens { range, command: Some(info_command), data: None }; - - lenses.push(info_lens); - - let profile_command = Command { - title: PROFILE_CODELENS_TITLE.to_string(), - command: PROFILE_COMMAND.into(), - arguments: Some(package_selection_args(&workspace, package)), - }; - - let profile_lens = CodeLens { range, command: Some(profile_command), data: None }; - - lenses.push(profile_lens); - } - } - } - - if lenses.is_empty() { - Ok(None) - } else { - Ok(Some(lenses)) - } -} diff --git a/tooling/lsp/src/requests/goto_definition.rs b/tooling/lsp/src/requests/goto_definition.rs new file mode 100644 index 0000000000..558851d4ec --- /dev/null +++ b/tooling/lsp/src/requests/goto_definition.rs @@ -0,0 +1,216 @@ +use std::future::{self, Future}; + +use crate::{types::GotoDefinitionResult, LspState}; +use async_lsp::{ErrorCode, LanguageClient, ResponseError}; +use fm::codespan_files::Error; +use lsp_types::{GotoDefinitionParams, GotoDefinitionResponse, Location}; +use lsp_types::{Position, Url}; +use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; + +pub(crate) fn on_goto_definition_request( + state: &mut LspState, + params: GotoDefinitionParams, +) -> impl Future> { + let result = on_goto_definition_inner(state, params); + future::ready(result) +} + +fn on_goto_definition_inner( + state: &mut LspState, + params: GotoDefinitionParams, +) -> Result { + let root_path = state.root_path.as_deref().ok_or_else(|| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not find project root") + })?; + + let file_path = + params.text_document_position_params.text_document.uri.to_file_path().map_err(|_| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") + })?; + + let toml_path = match find_package_manifest(root_path, &file_path) { + Ok(toml_path) => toml_path, + Err(err) => { + let _ = state.client.log_message(lsp_types::LogMessageParams { + typ: lsp_types::MessageType::WARNING, + message: err.to_string(), + }); + return Ok(None); + } + }; + let workspace = resolve_workspace_from_toml( + &toml_path, + PackageSelection::All, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + ) + .map_err(|err| { + // If we found a manifest, but the workspace is invalid, we raise an error about it + ResponseError::new(ErrorCode::REQUEST_FAILED, err) + })?; + + let mut definition_position = None; + + for package in &workspace { + let (mut context, crate_id) = nargo::prepare_package(package); + + // We ignore the warnings and errors produced by compilation while resolving the definition + let _ = noirc_driver::check_crate(&mut context, crate_id, false, false); + + let files = context.file_manager.as_file_map(); + let file_id = context.file_manager.name_to_id(file_path.clone()); + + if let Some(file_id) = file_id { + let byte_index = position_to_byte_index( + files, + file_id, + ¶ms.text_document_position_params.position, + ); + + if let Ok(byte_index) = byte_index { + let search_for_location = noirc_errors::Location { + file: file_id, + span: noirc_errors::Span::single_char(byte_index as u32), + }; + let found_location = context.get_definition_location_from(search_for_location); + + if let Some(found_location) = found_location { + let file_id = found_location.file; + definition_position = to_lsp_location(files, file_id, found_location.span); + } + } + } + } + + if let Some(definition_position) = definition_position { + let response: GotoDefinitionResponse = + GotoDefinitionResponse::from(definition_position).to_owned(); + Ok(Some(response)) + } else { + Ok(None) + } +} + +fn to_lsp_location<'a, F>( + files: &'a F, + file_id: F::FileId, + definition_span: noirc_errors::Span, +) -> Option +where + F: fm::codespan_files::Files<'a> + ?Sized, +{ + let range = crate::byte_span_to_range(files, file_id, definition_span.into())?; + let file_name = files.name(file_id).ok()?; + + let path = file_name.to_string(); + let uri = Url::from_file_path(path).ok()?; + + Some(Location { uri, range }) +} + +pub(crate) fn position_to_byte_index<'a, F>( + files: &'a F, + file_id: F::FileId, + position: &Position, +) -> Result +where + F: fm::codespan_files::Files<'a> + ?Sized, +{ + let source = files.source(file_id)?; + let source = source.as_ref(); + + let line_span = files.line_range(file_id, position.line as usize)?; + + let line_str = source.get(line_span.clone()); + + if let Some(line_str) = line_str { + let byte_offset = character_to_line_offset(line_str, position.character)?; + Ok(line_span.start + byte_offset) + } else { + Err(Error::InvalidCharBoundary { given: position.line as usize }) + } +} + +fn character_to_line_offset(line: &str, character: u32) -> Result { + let line_len = line.len(); + let mut character_offset = 0; + + let mut chars = line.chars(); + while let Some(ch) = chars.next() { + if character_offset == character { + let chars_off = chars.as_str().len(); + let ch_off = ch.len_utf8(); + + return Ok(line_len - chars_off - ch_off); + } + + character_offset += ch.len_utf16() as u32; + } + + // Handle positions after the last character on the line + if character_offset == character { + Ok(line_len) + } else { + Err(Error::ColumnTooLarge { given: character_offset as usize, max: line.len() }) + } +} + +#[cfg(test)] +mod goto_definition_tests { + + use async_lsp::ClientSocket; + use tokio::test; + + use crate::solver::MockBackend; + + use super::*; + + #[test] + async fn test_on_goto_definition() { + let client = ClientSocket::new_closed(); + let solver = MockBackend; + let mut state = LspState::new(&client, solver); + + let root_path = std::env::current_dir() + .unwrap() + .join("../../test_programs/execution_success/7_function") + .canonicalize() + .expect("Could not resolve root path"); + let noir_text_document = Url::from_file_path(root_path.join("src/main.nr").as_path()) + .expect("Could not convert text document path to URI"); + let root_uri = Some( + Url::from_file_path(root_path.as_path()).expect("Could not convert root path to URI"), + ); + + #[allow(deprecated)] + let initialize_params = lsp_types::InitializeParams { + process_id: Default::default(), + root_path: None, + root_uri, + initialization_options: None, + capabilities: Default::default(), + trace: Some(lsp_types::TraceValue::Verbose), + workspace_folders: None, + client_info: None, + locale: None, + }; + let _initialize_response = crate::requests::on_initialize(&mut state, initialize_params) + .await + .expect("Could not initialize LSP server"); + + let params = GotoDefinitionParams { + text_document_position_params: lsp_types::TextDocumentPositionParams { + text_document: lsp_types::TextDocumentIdentifier { uri: noir_text_document }, + position: Position { line: 95, character: 5 }, + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }; + + let response = on_goto_definition_request(&mut state, params) + .await + .expect("Could execute on_goto_definition_request"); + + assert!(&response.is_some()); + } +} diff --git a/tooling/lsp/src/requests/mod.rs b/tooling/lsp/src/requests/mod.rs index b2be24e118..e2fdcdf08d 100644 --- a/tooling/lsp/src/requests/mod.rs +++ b/tooling/lsp/src/requests/mod.rs @@ -1,7 +1,9 @@ use std::future::Future; -use crate::types::{CodeLensOptions, InitializeParams, TextDocumentSyncOptions}; +use crate::types::InitializeParams; use async_lsp::ResponseError; +use lsp_types::{Position, TextDocumentSyncCapability, TextDocumentSyncKind}; +use nargo_fmt::Config; use crate::{ types::{InitializeResult, NargoCapability, NargoTestsOptions, ServerCapabilities}, @@ -18,13 +20,13 @@ use crate::{ // They are not attached to the `NargoLspService` struct so they can be unit tested with only `LspState` // and params passed in. -mod code_lens_request; +mod goto_definition; mod profile_run; mod test_run; mod tests; pub(crate) use { - code_lens_request::on_code_lens_request, profile_run::on_profile_run_request, + goto_definition::on_goto_definition_request, profile_run::on_profile_run_request, test_run::on_test_run_request, tests::on_tests_request, }; @@ -35,10 +37,7 @@ pub(crate) fn on_initialize( state.root_path = params.root_uri.and_then(|root_uri| root_uri.to_file_path().ok()); async { - let text_document_sync = - TextDocumentSyncOptions { save: Some(true.into()), ..Default::default() }; - - let code_lens = CodeLensOptions { resolve_provider: Some(false) }; + let text_document_sync = TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL); let nargo = NargoCapability { tests: Some(NargoTestsOptions { @@ -50,15 +49,52 @@ pub(crate) fn on_initialize( Ok(InitializeResult { capabilities: ServerCapabilities { - text_document_sync: Some(text_document_sync.into()), - code_lens_provider: Some(code_lens), + text_document_sync: Some(text_document_sync), + document_formatting_provider: true, nargo: Some(nargo), + definition_provider: Some(lsp_types::OneOf::Left(true)), }, server_info: None, }) } } +pub(crate) fn on_formatting( + state: &mut LspState, + params: lsp_types::DocumentFormattingParams, +) -> impl Future>, ResponseError>> { + std::future::ready(on_formatting_inner(state, params)) +} + +fn on_formatting_inner( + state: &LspState, + params: lsp_types::DocumentFormattingParams, +) -> Result>, ResponseError> { + let path = params.text_document.uri.to_string(); + + if let Some(source) = state.input_files.get(&path) { + let (module, errors) = noirc_frontend::parse_program(source); + if !errors.is_empty() { + return Ok(None); + } + + let new_text = nargo_fmt::format(source, module, &Config::default()); + + let start_position = Position { line: 0, character: 0 }; + let end_position = Position { + line: source.lines().count() as u32, + character: source.chars().count() as u32, + }; + + Ok(Some(vec![lsp_types::TextEdit { + range: lsp_types::Range::new(start_position, end_position), + new_text, + }])) + } else { + Ok(None) + } +} + pub(crate) fn on_shutdown( _state: &mut LspState, _params: (), @@ -69,9 +105,7 @@ pub(crate) fn on_shutdown( #[cfg(test)] mod initialization { use async_lsp::ClientSocket; - use lsp_types::{ - CodeLensOptions, InitializeParams, TextDocumentSyncCapability, TextDocumentSyncOptions, - }; + use lsp_types::{InitializeParams, TextDocumentSyncCapability, TextDocumentSyncKind}; use tokio::test; use crate::{ @@ -88,10 +122,10 @@ mod initialization { assert!(matches!( response.capabilities, ServerCapabilities { - text_document_sync: Some(TextDocumentSyncCapability::Options( - TextDocumentSyncOptions { save: Some(_), .. } + text_document_sync: Some(TextDocumentSyncCapability::Kind( + TextDocumentSyncKind::FULL )), - code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(false) }), + document_formatting_provider: true, .. } )); diff --git a/tooling/lsp/src/requests/test_run.rs b/tooling/lsp/src/requests/test_run.rs index 962fe99a49..e5245de426 100644 --- a/tooling/lsp/src/requests/test_run.rs +++ b/tooling/lsp/src/requests/test_run.rs @@ -10,7 +10,6 @@ use noirc_driver::{check_crate, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::hir::FunctionNameMatch; use crate::{ - get_non_stdlib_asset, types::{NargoTestRunParams, NargoTestRunResult}, LspState, }; @@ -51,8 +50,8 @@ fn on_test_run_request_inner( // Since we filtered on crate name, this should be the only item in the iterator match workspace.into_iter().next() { Some(package) => { - let (mut context, crate_id) = prepare_package(package, Box::new(get_non_stdlib_asset)); - if check_crate(&mut context, crate_id, false).is_err() { + let (mut context, crate_id) = prepare_package(package); + if check_crate(&mut context, crate_id, false, false).is_err() { let result = NargoTestRunResult { id: params.id.clone(), result: "error".to_string(), diff --git a/tooling/lsp/src/requests/tests.rs b/tooling/lsp/src/requests/tests.rs index 6b94b921a0..9a67eaae6d 100644 --- a/tooling/lsp/src/requests/tests.rs +++ b/tooling/lsp/src/requests/tests.rs @@ -7,7 +7,7 @@ use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSele use noirc_driver::{check_crate, NOIR_ARTIFACT_VERSION_STRING}; use crate::{ - get_non_stdlib_asset, get_package_tests_in_crate, + get_package_tests_in_crate, types::{NargoPackageTests, NargoTestsParams, NargoTestsResult}, LspState, }; @@ -53,10 +53,10 @@ fn on_tests_request_inner( let package_tests: Vec<_> = workspace .into_iter() .filter_map(|package| { - let (mut context, crate_id) = prepare_package(package, Box::new(get_non_stdlib_asset)); + let (mut context, crate_id) = prepare_package(package); // We ignore the warnings and errors produced by compilation for producing tests // because we can still get the test functions even if compilation fails - let _ = check_crate(&mut context, crate_id, false); + let _ = check_crate(&mut context, crate_id, false, false); // We don't add test headings for a package if it contains no `#[test]` functions get_package_tests_in_crate(&context, &crate_id, &package.name) diff --git a/tooling/lsp/src/types.rs b/tooling/lsp/src/types.rs index 7a50c53805..48c412eb5a 100644 --- a/tooling/lsp/src/types.rs +++ b/tooling/lsp/src/types.rs @@ -1,4 +1,5 @@ use fm::FileId; +use lsp_types::{DefinitionOptions, OneOf}; use noirc_driver::DebugFile; use noirc_errors::{debug_info::OpCodesCount, Location}; use noirc_frontend::graph::CrateName; @@ -8,11 +9,10 @@ use std::collections::{BTreeMap, HashMap}; // Re-providing lsp_types that we don't need to override pub(crate) use lsp_types::{ - CodeLens, CodeLensOptions, CodeLensParams, Command, Diagnostic, DiagnosticSeverity, - DidChangeConfigurationParams, DidChangeTextDocumentParams, DidCloseTextDocumentParams, - DidOpenTextDocumentParams, DidSaveTextDocumentParams, InitializeParams, InitializedParams, - LogMessageParams, MessageType, Position, PublishDiagnosticsParams, Range, ServerInfo, - TextDocumentSyncCapability, TextDocumentSyncOptions, Url, + Diagnostic, DiagnosticSeverity, DidChangeConfigurationParams, DidChangeTextDocumentParams, + DidCloseTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams, + InitializeParams, InitializedParams, LogMessageParams, MessageType, Position, + PublishDiagnosticsParams, Range, ServerInfo, TextDocumentSyncCapability, Url, }; pub(crate) mod request { @@ -24,7 +24,7 @@ pub(crate) mod request { }; // Re-providing lsp_types that we don't need to override - pub(crate) use lsp_types::request::{CodeLensRequest as CodeLens, Shutdown}; + pub(crate) use lsp_types::request::{Formatting, GotoDefinition, Shutdown}; #[derive(Debug)] pub(crate) struct Initialize; @@ -108,9 +108,12 @@ pub(crate) struct ServerCapabilities { #[serde(skip_serializing_if = "Option::is_none")] pub(crate) text_document_sync: Option, - /// The server provides code lens. + /// The server provides goto definition support. #[serde(skip_serializing_if = "Option::is_none")] - pub(crate) code_lens_provider: Option, + pub(crate) definition_provider: Option>, + + /// The server provides document formatting. + pub(crate) document_formatting_provider: bool, /// The server handles and provides custom nargo messages. #[serde(skip_serializing_if = "Option::is_none")] @@ -211,4 +214,4 @@ pub(crate) struct NargoProfileRunResult { pub(crate) opcodes_counts: HashMap, } -pub(crate) type CodeLensResult = Option>; +pub(crate) type GotoDefinitionResult = Option; diff --git a/tooling/nargo/Cargo.toml b/tooling/nargo/Cargo.toml index f826945996..48741c367a 100644 --- a/tooling/nargo/Cargo.toml +++ b/tooling/nargo/Cargo.toml @@ -24,4 +24,9 @@ iter-extended.workspace = true serde.workspace = true thiserror.workspace = true codespan-reporting.workspace = true -rayon = "1.8.0" \ No newline at end of file +rayon = "1.8.0" + +[dev-dependencies] +# TODO: This dependency is used to generate unit tests for `get_all_paths_in_dir` +# TODO: once that method is moved to nargo_cli, we can move this dependency to nargo_cli +tempfile = "3.2.0" \ No newline at end of file diff --git a/tooling/nargo/src/constants.rs b/tooling/nargo/src/constants.rs index 5e44827769..ff8da403c6 100644 --- a/tooling/nargo/src/constants.rs +++ b/tooling/nargo/src/constants.rs @@ -20,4 +20,4 @@ pub const PKG_FILE: &str = "Nargo.toml"; /// The extension for files containing circuit proofs. pub const PROOF_EXT: &str = "proof"; /// The extension for files containing proof witnesses. -pub const WITNESS_EXT: &str = "tr"; +pub const WITNESS_EXT: &str = "gz"; diff --git a/tooling/nargo/src/lib.rs b/tooling/nargo/src/lib.rs index ef014fb436..6f3d36febb 100644 --- a/tooling/nargo/src/lib.rs +++ b/tooling/nargo/src/lib.rs @@ -16,7 +16,7 @@ pub mod workspace; use std::collections::BTreeMap; -use fm::{FileManager, FileReader}; +use fm::FileManager; use noirc_driver::{add_dep, prepare_crate, prepare_dependency}; use noirc_frontend::{ graph::{CrateGraph, CrateId, CrateName}, @@ -42,9 +42,55 @@ pub fn prepare_dependencies( } } -pub fn prepare_package(package: &Package, file_reader: Box) -> (Context, CrateId) { - // TODO: FileManager continues to leak into various crates - let fm = FileManager::new(&package.root_dir, file_reader); +// We will pre-populate the file manager with all the files in the package +// This is so that we can avoid having to read from disk when we are compiling +// +// This does not require parsing because we are interested in the files under the src directory +// it may turn out that we do not need to include some Noir files that we add to the file +// manager +pub fn insert_all_files_for_package_into_file_manager( + package: &Package, + file_manager: &mut FileManager, +) { + // Start off at the entry path and read all files in the parent directory. + let entry_path_parent = package + .entry_path + .parent() + .unwrap_or_else(|| panic!("The entry path is expected to be a single file within a directory and so should have a parent {:?}", package.entry_path)) + .clone(); + + // Get all files in the package and add them to the file manager + let paths = + get_all_paths_in_dir(entry_path_parent).expect("could not get all paths in the package"); + for path in paths { + let source = std::fs::read_to_string(path.as_path()) + .unwrap_or_else(|_| panic!("could not read file {:?} into string", path)); + file_manager.add_file_with_source(path.as_path(), source); + } + + insert_all_files_for_packages_dependencies_into_file_manager(package, file_manager); +} + +// Inserts all files for the dependencies of the package into the file manager +// too +fn insert_all_files_for_packages_dependencies_into_file_manager( + package: &Package, + file_manager: &mut FileManager, +) { + for (_, dep) in package.dependencies.iter() { + match dep { + Dependency::Local { package } | Dependency::Remote { package } => { + insert_all_files_for_package_into_file_manager(package, file_manager); + insert_all_files_for_packages_dependencies_into_file_manager(package, file_manager); + } + } + } +} + +pub fn prepare_package(package: &Package) -> (Context, CrateId) { + let mut fm = FileManager::new(&package.root_dir); + insert_all_files_for_package_into_file_manager(package, &mut fm); + let graph = CrateGraph::default(); let mut context = Context::new(fm, graph); @@ -54,3 +100,72 @@ pub fn prepare_package(package: &Package, file_reader: Box) -> (Cont (context, crate_id) } + +// Get all paths in the directory and subdirectories. +// +// Panics: If the path is not a path to a directory. +// +// TODO: Along with prepare_package, this function is an abstraction leak +// TODO: given that this crate should not know about the file manager. +// TODO: We can clean this up in a future refactor +fn get_all_paths_in_dir(dir: &std::path::Path) -> std::io::Result> { + assert!(dir.is_dir(), "directory {dir:?} is not a path to a directory"); + + let mut paths = Vec::new(); + + if dir.is_dir() { + for entry in std::fs::read_dir(dir)? { + let entry = entry?; + let path = entry.path(); + if path.is_dir() { + let mut sub_paths = get_all_paths_in_dir(&path)?; + paths.append(&mut sub_paths); + } else { + paths.push(path); + } + } + } + + Ok(paths) +} + +#[cfg(test)] +mod tests { + use crate::get_all_paths_in_dir; + use std::{ + fs::{self, File}, + path::Path, + }; + use tempfile::tempdir; + + fn create_test_dir_structure(temp_dir: &Path) -> std::io::Result<()> { + fs::create_dir(temp_dir.join("subdir1"))?; + File::create(temp_dir.join("subdir1/file1.txt"))?; + fs::create_dir(temp_dir.join("subdir2"))?; + File::create(temp_dir.join("subdir2/file2.txt"))?; + File::create(temp_dir.join("file3.txt"))?; + Ok(()) + } + + #[test] + fn test_get_all_paths_in_dir() { + let temp_dir = tempdir().expect("could not create a temporary directory"); + create_test_dir_structure(temp_dir.path()) + .expect("could not create test directory structure"); + + let paths = get_all_paths_in_dir(temp_dir.path()) + .expect("could not get all paths in the test directory"); + + // This should be the paths to all of the files in the directory and the subdirectory + let expected_paths = vec![ + temp_dir.path().join("file3.txt"), + temp_dir.path().join("subdir1/file1.txt"), + temp_dir.path().join("subdir2/file2.txt"), + ]; + + assert_eq!(paths.len(), expected_paths.len()); + for path in expected_paths { + assert!(paths.contains(&path)); + } + } +} diff --git a/tooling/nargo/src/ops/compile.rs b/tooling/nargo/src/ops/compile.rs index d4164eaa86..59ac5672a1 100644 --- a/tooling/nargo/src/ops/compile.rs +++ b/tooling/nargo/src/ops/compile.rs @@ -70,8 +70,7 @@ pub fn compile_program( np_language: Language, is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> (FileManager, CompilationResult) { - let (mut context, crate_id) = - prepare_package(package, Box::new(|path| std::fs::read_to_string(path))); + let (mut context, crate_id) = prepare_package(package); let program_artifact_path = workspace.package_build_path(package); let mut debug_artifact_path = program_artifact_path.clone(); @@ -85,22 +84,9 @@ pub fn compile_program( } }; - // TODO: we say that pedersen hashing is supported by all backends for now - let is_opcode_supported_pedersen_hash = |opcode: &Opcode| -> bool { - if let Opcode::BlackBoxFuncCall( - acvm::acir::circuit::opcodes::BlackBoxFuncCall::PedersenHash { .. }, - ) = opcode - { - true - } else { - is_opcode_supported(opcode) - } - }; - // Apply backend specific optimizations. - let optimized_program = - crate::ops::optimize_program(program, np_language, &is_opcode_supported_pedersen_hash) - .expect("Backend does not support an opcode that is in the IR"); + let optimized_program = crate::ops::optimize_program(program, np_language, is_opcode_supported) + .expect("Backend does not support an opcode that is in the IR"); (context.file_manager, Ok((optimized_program, warnings))) } @@ -111,8 +97,7 @@ fn compile_contract( np_language: Language, is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> (FileManager, CompilationResult) { - let (mut context, crate_id) = - prepare_package(package, Box::new(|path| std::fs::read_to_string(path))); + let (mut context, crate_id) = prepare_package(package); let (contract, warnings) = match noirc_driver::compile_contract(&mut context, crate_id, compile_options) { Ok(contracts_and_warnings) => contracts_and_warnings, diff --git a/tooling/nargo/src/ops/foreign_calls.rs b/tooling/nargo/src/ops/foreign_calls.rs index 6cc78febab..bc1e19cdcf 100644 --- a/tooling/nargo/src/ops/foreign_calls.rs +++ b/tooling/nargo/src/ops/foreign_calls.rs @@ -2,7 +2,6 @@ use acvm::{ acir::brillig::{ForeignCallParam, ForeignCallResult, Value}, pwg::ForeignCallWaitInfo, }; -use iter_extended::vecmap; use noirc_printable_type::{decode_string_value, ForeignCallError, PrintableValueDisplay}; pub trait ForeignCallExecutor { @@ -15,9 +14,7 @@ pub trait ForeignCallExecutor { /// This enumeration represents the Brillig foreign calls that are natively supported by nargo. /// After resolution of a foreign call, nargo will restart execution of the ACVM pub(crate) enum ForeignCall { - Println, - Sequence, - ReverseSequence, + Print, CreateMock, SetMockParams, SetMockReturns, @@ -34,9 +31,7 @@ impl std::fmt::Display for ForeignCall { impl ForeignCall { pub(crate) fn name(&self) -> &'static str { match self { - ForeignCall::Println => "println", - ForeignCall::Sequence => "get_number_sequence", - ForeignCall::ReverseSequence => "get_reverse_number_sequence", + ForeignCall::Print => "print", ForeignCall::CreateMock => "create_mock", ForeignCall::SetMockParams => "set_mock_params", ForeignCall::SetMockReturns => "set_mock_returns", @@ -47,9 +42,7 @@ impl ForeignCall { pub(crate) fn lookup(op_name: &str) -> Option { match op_name { - "println" => Some(ForeignCall::Println), - "get_number_sequence" => Some(ForeignCall::Sequence), - "get_reverse_number_sequence" => Some(ForeignCall::ReverseSequence), + "print" => Some(ForeignCall::Print), "create_mock" => Some(ForeignCall::CreateMock), "set_mock_params" => Some(ForeignCall::SetMockParams), "set_mock_returns" => Some(ForeignCall::SetMockReturns), @@ -99,7 +92,7 @@ pub struct DefaultForeignCallExecutor { last_mock_id: usize, /// The registered mocks mocked_responses: Vec, - /// Whether to print [`ForeignCall::Println`] output. + /// Whether to print [`ForeignCall::Print`] output. show_output: bool, } @@ -127,9 +120,14 @@ impl DefaultForeignCallExecutor { decode_string_value(&fields) } - fn execute_println(foreign_call_inputs: &[ForeignCallParam]) -> Result<(), ForeignCallError> { - let display_values: PrintableValueDisplay = foreign_call_inputs.try_into()?; - println!("{display_values}"); + fn execute_print(foreign_call_inputs: &[ForeignCallParam]) -> Result<(), ForeignCallError> { + let skip_newline = foreign_call_inputs[0].unwrap_value().is_zero(); + let display_values: PrintableValueDisplay = foreign_call_inputs + .split_first() + .ok_or(ForeignCallError::MissingForeignCallInputs)? + .1 + .try_into()?; + print!("{display_values}{}", if skip_newline { "" } else { "\n" }); Ok(()) } } @@ -141,36 +139,12 @@ impl ForeignCallExecutor for DefaultForeignCallExecutor { ) -> Result { let foreign_call_name = foreign_call.function.as_str(); match ForeignCall::lookup(foreign_call_name) { - Some(ForeignCall::Println) => { + Some(ForeignCall::Print) => { if self.show_output { - Self::execute_println(&foreign_call.inputs)?; + Self::execute_print(&foreign_call.inputs)?; } Ok(ForeignCallResult { values: vec![] }) } - Some(ForeignCall::Sequence) => { - let sequence_length: u128 = - foreign_call.inputs[0].unwrap_value().to_field().to_u128(); - let sequence = vecmap(0..sequence_length, Value::from); - - Ok(ForeignCallResult { - values: vec![ - ForeignCallParam::Single(sequence_length.into()), - ForeignCallParam::Array(sequence), - ], - }) - } - Some(ForeignCall::ReverseSequence) => { - let sequence_length: u128 = - foreign_call.inputs[0].unwrap_value().to_field().to_u128(); - let sequence = vecmap((0..sequence_length).rev(), Value::from); - - Ok(ForeignCallResult { - values: vec![ - ForeignCallParam::Single(sequence_length.into()), - ForeignCallParam::Array(sequence), - ], - }) - } Some(ForeignCall::CreateMock) => { let mock_oracle_name = Self::parse_string(&foreign_call.inputs[0]); assert!(ForeignCall::lookup(&mock_oracle_name).is_none()); diff --git a/tooling/nargo/src/package.rs b/tooling/nargo/src/package.rs index 94c7c5b9c9..ecbf358521 100644 --- a/tooling/nargo/src/package.rs +++ b/tooling/nargo/src/package.rs @@ -43,6 +43,7 @@ impl Dependency { #[derive(Clone)] pub struct Package { + pub version: Option, // A semver string which specifies the compiler version required to compile this package pub compiler_required_version: Option, pub root_dir: PathBuf, diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index 1a08514dc5..008b1233cd 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -43,14 +43,21 @@ tower.workspace = true async-lsp = { workspace = true, features = ["client-monitor", "stdio", "tracing", "tokio"] } const_format.workspace = true hex.workspace = true +similar-asserts.workspace = true termcolor = "1.1.2" color-eyre = "0.6.2" +env_logger = "0.9.0" tokio = { version = "1.0", features = ["io-std"] } # Backends backend-interface = { path = "../backend_interface" } bb_abstraction_leaks.workspace = true +# Logs +tracing.workspace = true +tracing-subscriber = "0.3.18" +tracing-appender = "0.2.3" + [target.'cfg(not(unix))'.dependencies] tokio-util = { version = "0.7.8", features = ["compat"] } diff --git a/tooling/nargo_cli/build.rs b/tooling/nargo_cli/build.rs index 0d1acca6ee..6f6d65ee89 100644 --- a/tooling/nargo_cli/build.rs +++ b/tooling/nargo_cli/build.rs @@ -33,11 +33,11 @@ fn main() { // Try to find the directory that Cargo sets when it is running; otherwise fallback to assuming the CWD // is the root of the repository and append the crate path - let manifest_dir = match std::env::var("CARGO_MANIFEST_DIR") { - Ok(dir) => PathBuf::from(dir), - Err(_) => std::env::current_dir().unwrap().join("crates").join("nargo_cli"), + let root_dir = match std::env::var("CARGO_MANIFEST_DIR") { + Ok(dir) => PathBuf::from(dir).parent().unwrap().parent().unwrap().to_path_buf(), + Err(_) => std::env::current_dir().unwrap(), }; - let test_dir = manifest_dir.join("tests"); + let test_dir = root_dir.join("test_programs"); generate_execution_success_tests(&mut test_file, &test_dir); generate_noir_test_success_tests(&mut test_file, &test_dir); @@ -201,7 +201,9 @@ fn compile_success_empty_{test_name}() {{ }} // `compile_success_empty` tests should be able to compile down to an empty circuit. - let json: serde_json::Value = serde_json::from_slice(&output.stdout).expect("JSON was not well-formatted"); + let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap_or_else(|_| {{ + panic!("JSON was not well-formatted {{:?}}",output.stdout) + }}); let num_opcodes = &json["programs"][0]["acir_opcodes"]; assert_eq!(num_opcodes.as_u64().unwrap(), 0); }} diff --git a/tooling/nargo_cli/src/cli/check_cmd.rs b/tooling/nargo_cli/src/cli/check_cmd.rs index 57b36b8932..0ea8186a23 100644 --- a/tooling/nargo_cli/src/cli/check_cmd.rs +++ b/tooling/nargo_cli/src/cli/check_cmd.rs @@ -55,12 +55,12 @@ pub(crate) fn run( } fn check_package(package: &Package, compile_options: &CompileOptions) -> Result<(), CompileError> { - let (mut context, crate_id) = - prepare_package(package, Box::new(|path| std::fs::read_to_string(path))); + let (mut context, crate_id) = prepare_package(package); check_crate_and_report_errors( &mut context, crate_id, compile_options.deny_warnings, + compile_options.disable_macros, compile_options.silence_warnings, )?; @@ -182,9 +182,10 @@ pub(crate) fn check_crate_and_report_errors( context: &mut Context, crate_id: CrateId, deny_warnings: bool, + disable_macros: bool, silence_warnings: bool, ) -> Result<(), CompileError> { - let result = check_crate(context, crate_id, deny_warnings); + let result = check_crate(context, crate_id, deny_warnings, disable_macros); super::compile_cmd::report_errors( result, &context.file_manager, diff --git a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index 59143526b2..02c83adb59 100644 --- a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -6,8 +6,8 @@ use super::{ use crate::backends::Backend; use crate::errors::CliError; -use acvm::acir::circuit::Opcode; use acvm::Language; +use backend_interface::BackendOpcodeSupport; use bb_abstraction_leaks::ACVM_BACKEND_BARRETENBERG; use clap::Args; use nargo::package::Package; @@ -54,7 +54,7 @@ pub(crate) fn run( package, &args.compile_options, np_language, - &|opcode| opcode_support.is_opcode_supported(opcode), + &opcode_support, )?; let contract_dir = workspace.contracts_directory_path(package); @@ -74,15 +74,10 @@ fn smart_contract_for_package( package: &Package, compile_options: &CompileOptions, np_language: Language, - is_opcode_supported: &impl Fn(&Opcode) -> bool, + opcode_support: &BackendOpcodeSupport, ) -> Result { - let program = compile_bin_package( - workspace, - package, - compile_options, - np_language, - &is_opcode_supported, - )?; + let program = + compile_bin_package(workspace, package, compile_options, np_language, opcode_support)?; let mut smart_contract_string = backend.eth_contract(&program.circuit)?; diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index 9ffbc26828..043c084195 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -1,6 +1,5 @@ use std::path::Path; -use acvm::acir::circuit::opcodes::BlackBoxFuncCall; use acvm::acir::circuit::Opcode; use acvm::Language; use backend_interface::BackendOpcodeSupport; @@ -24,6 +23,7 @@ use clap::Args; use crate::backends::Backend; use crate::errors::CliError; +use super::fs::program::only_acir; use super::fs::program::{ read_debug_artifact_from_file, read_program_from_file, save_contract_to_file, save_debug_artifact_to_file, save_program_to_file, @@ -37,10 +37,6 @@ const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg"; /// Compile the program and its secret execution trace into ACIR format #[derive(Debug, Clone, Args)] pub(crate) struct CompileCommand { - /// Include Proving and Verification keys in the build artifacts. - #[arg(long)] - include_keys: bool, - /// The name of the package to compile #[clap(long, conflicts_with = "workspace")] package: Option, @@ -76,7 +72,7 @@ pub(crate) fn run( .cloned() .partition(|package| package.is_binary()); - let (np_language, opcode_support) = backend.get_backend_info()?; + let (np_language, opcode_support) = backend.get_backend_info_or_default(); let (_, compiled_contracts) = compile_workspace( &workspace, &binary_packages, @@ -102,12 +98,11 @@ pub(super) fn compile_workspace( opcode_support: &BackendOpcodeSupport, compile_options: &CompileOptions, ) -> Result<(Vec, Vec), CliError> { - let is_opcode_supported = |opcode: &_| opcode_support.is_opcode_supported(opcode); - // Compile all of the packages in parallel. let program_results: Vec<(FileManager, CompilationResult)> = binary_packages .par_iter() .map(|package| { + let is_opcode_supported = |opcode: &_| opcode_support.is_opcode_supported(opcode); compile_program(workspace, package, compile_options, np_language, &is_opcode_supported) }) .collect(); @@ -115,6 +110,7 @@ pub(super) fn compile_workspace( contract_packages .par_iter() .map(|package| { + let is_opcode_supported = |opcode: &_| opcode_support.is_opcode_supported(opcode); compile_contract(package, compile_options, np_language, &is_opcode_supported) }) .collect(); @@ -151,14 +147,16 @@ pub(crate) fn compile_bin_package( package: &Package, compile_options: &CompileOptions, np_language: Language, - is_opcode_supported: &impl Fn(&Opcode) -> bool, + opcode_support: &BackendOpcodeSupport, ) -> Result { if package.is_library() { return Err(CompileError::LibraryCrate(package.name.clone()).into()); } let (file_manager, compilation_result) = - compile_program(workspace, package, compile_options, np_language, &is_opcode_supported); + compile_program(workspace, package, compile_options, np_language, &|opcode| { + opcode_support.is_opcode_supported(opcode) + }); let program = report_errors( compilation_result, @@ -177,8 +175,7 @@ fn compile_program( np_language: Language, is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> (FileManager, CompilationResult) { - let (mut context, crate_id) = - prepare_package(package, Box::new(|path| std::fs::read_to_string(path))); + let (mut context, crate_id) = prepare_package(package); let program_artifact_path = workspace.package_build_path(package); let mut debug_artifact_path = program_artifact_path.clone(); @@ -215,21 +212,11 @@ fn compile_program( } }; - // TODO: we say that pedersen hashing is supported by all backends for now - let is_opcode_supported_pedersen_hash = |opcode: &Opcode| -> bool { - if let Opcode::BlackBoxFuncCall(BlackBoxFuncCall::PedersenHash { .. }) = opcode { - true - } else { - is_opcode_supported(opcode) - } - }; - // Apply backend specific optimizations. - let optimized_program = - nargo::ops::optimize_program(program, np_language, &is_opcode_supported_pedersen_hash) - .expect("Backend does not support an opcode that is in the IR"); - - save_program(optimized_program.clone(), package, &workspace.target_directory_path()); + let optimized_program = nargo::ops::optimize_program(program, np_language, is_opcode_supported) + .expect("Backend does not support an opcode that is in the IR"); + let only_acir = compile_options.only_acir; + save_program(optimized_program.clone(), package, &workspace.target_directory_path(), only_acir); (context.file_manager, Ok((optimized_program, warnings))) } @@ -240,8 +227,7 @@ fn compile_contract( np_language: Language, is_opcode_supported: &impl Fn(&Opcode) -> bool, ) -> (FileManager, CompilationResult) { - let (mut context, crate_id) = - prepare_package(package, Box::new(|path| std::fs::read_to_string(path))); + let (mut context, crate_id) = prepare_package(package); let (contract, warnings) = match noirc_driver::compile_contract(&mut context, crate_id, compile_options) { Ok(contracts_and_warnings) => contracts_and_warnings, @@ -257,7 +243,12 @@ fn compile_contract( (context.file_manager, Ok((optimized_contract, warnings))) } -fn save_program(program: CompiledProgram, package: &Package, circuit_dir: &Path) { +fn save_program( + program: CompiledProgram, + package: &Package, + circuit_dir: &Path, + only_acir_opt: bool, +) { let preprocessed_program = PreprocessedProgram { hash: program.hash, backend: String::from(BACKEND_IDENTIFIER), @@ -265,8 +256,11 @@ fn save_program(program: CompiledProgram, package: &Package, circuit_dir: &Path) noir_version: program.noir_version, bytecode: program.circuit, }; - - save_program_to_file(&preprocessed_program, &package.name, circuit_dir); + if only_acir_opt { + only_acir(&preprocessed_program, circuit_dir); + } else { + save_program_to_file(&preprocessed_program, &package.name, circuit_dir); + } let debug_artifact = DebugArtifact { debug_symbols: vec![program.debug], diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 1d34405831..5204e0f122 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use acvm::acir::native_types::WitnessMap; use clap::Args; @@ -56,32 +58,50 @@ pub(crate) fn run( return Ok(()); }; - let compiled_program = - compile_bin_package(&workspace, package, &args.compile_options, np_language, &|opcode| { - opcode_support.is_opcode_supported(opcode) - })?; + let compiled_program = compile_bin_package( + &workspace, + package, + &args.compile_options, + np_language, + &opcode_support, + )?; - println!("[{}] Starting debugger", package.name); - let (return_value, solved_witness) = - debug_program_and_decode(compiled_program, package, &args.prover_name)?; + run_async(package, compiled_program, &args.prover_name, &args.witness_name, target_dir) +} - if let Some(solved_witness) = solved_witness { - println!("[{}] Circuit witness successfully solved", package.name); +fn run_async( + package: &Package, + program: CompiledProgram, + prover_name: &str, + witness_name: &Option, + target_dir: &PathBuf, +) -> Result<(), CliError> { + use tokio::runtime::Builder; + let runtime = Builder::new_current_thread().enable_all().build().unwrap(); - if let Some(return_value) = return_value { - println!("[{}] Circuit output: {return_value:?}", package.name); - } + runtime.block_on(async { + println!("[{}] Starting debugger", package.name); + let (return_value, solved_witness) = + debug_program_and_decode(program, package, prover_name)?; + + if let Some(solved_witness) = solved_witness { + println!("[{}] Circuit witness successfully solved", package.name); - if let Some(witness_name) = &args.witness_name { - let witness_path = save_witness_to_dir(solved_witness, witness_name, target_dir)?; + if let Some(return_value) = return_value { + println!("[{}] Circuit output: {return_value:?}", package.name); + } - println!("[{}] Witness saved to {}", package.name, witness_path.display()); + if let Some(witness_name) = witness_name { + let witness_path = save_witness_to_dir(solved_witness, witness_name, target_dir)?; + + println!("[{}] Witness saved to {}", package.name, witness_path.display()); + } + } else { + println!("Debugger execution halted."); } - } else { - println!("Debugger execution halted."); - } - Ok(()) + Ok(()) + }) } fn debug_program_and_decode( diff --git a/tooling/nargo_cli/src/cli/execute_cmd.rs b/tooling/nargo_cli/src/cli/execute_cmd.rs index 91e4b80045..2f69b4c7df 100644 --- a/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -56,14 +56,14 @@ pub(crate) fn run( )?; let target_dir = &workspace.target_directory_path(); - let (np_language, opcode_support) = backend.get_backend_info()?; + let (np_language, opcode_support) = backend.get_backend_info_or_default(); for package in &workspace { let compiled_program = compile_bin_package( &workspace, package, &args.compile_options, np_language, - &|opcode| opcode_support.is_opcode_supported(opcode), + &opcode_support, )?; let (return_value, solved_witness) = diff --git a/tooling/nargo_cli/src/cli/fmt_cmd.rs b/tooling/nargo_cli/src/cli/fmt_cmd.rs index eaa66fff02..0c2ca71eba 100644 --- a/tooling/nargo_cli/src/cli/fmt_cmd.rs +++ b/tooling/nargo_cli/src/cli/fmt_cmd.rs @@ -2,6 +2,7 @@ use std::{fs::DirEntry, path::Path}; use clap::Args; use fm::FileManager; +use nargo::insert_all_files_for_package_into_file_manager; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; use noirc_errors::CustomDiagnostic; @@ -11,10 +12,17 @@ use crate::errors::CliError; use super::NargoConfig; +/// Format the Noir files in a workspace #[derive(Debug, Clone, Args)] -pub(crate) struct FormatCommand {} +pub(crate) struct FormatCommand { + /// Run noirfmt in check mode + #[arg(long)] + check: bool, +} + +pub(crate) fn run(args: FormatCommand, config: NargoConfig) -> Result<(), CliError> { + let check_mode = args.check; -pub(crate) fn run(_args: FormatCommand, config: NargoConfig) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let workspace = resolve_workspace_from_toml( &toml_path, @@ -25,12 +33,14 @@ pub(crate) fn run(_args: FormatCommand, config: NargoConfig) -> Result<(), CliEr let config = nargo_fmt::Config::read(&config.program_dir) .map_err(|err| CliError::Generic(err.to_string()))?; + let mut check_exit_code_one = false; + for package in &workspace { - let mut file_manager = - FileManager::new(&package.root_dir, Box::new(|path| std::fs::read_to_string(path))); + let mut file_manager = FileManager::new(&package.root_dir); + insert_all_files_for_package_into_file_manager(package, &mut file_manager); visit_noir_files(&package.root_dir.join("src"), &mut |entry| { - let file_id = file_manager.add_file(&entry.path()).expect("file exists"); + let file_id = file_manager.name_to_id(entry.path().to_path_buf()).expect("The file should exist since we added all files in the package into the file manager"); let (parsed_module, errors) = parse_file(&file_manager, file_id); let is_all_warnings = errors.iter().all(ParserError::is_warning); @@ -52,16 +62,40 @@ pub(crate) fn run(_args: FormatCommand, config: NargoConfig) -> Result<(), CliEr return Ok(()); } - let source = nargo_fmt::format( - file_manager.fetch_file(file_id).source(), - parsed_module, - &config, - ); + let original = file_manager.fetch_file(file_id).source(); + let formatted = nargo_fmt::format(original, parsed_module, &config); + + if check_mode { + let diff = similar_asserts::SimpleDiff::from_str( + original, + &formatted, + "original", + "formatted", + ) + .to_string(); + + if !diff.lines().next().is_some_and(|line| line.contains("Invisible differences")) { + if !check_exit_code_one { + check_exit_code_one = true; + } - std::fs::write(entry.path(), source) + println!("{diff}"); + } + + Ok(()) + } else { + std::fs::write(entry.path(), formatted) + } }) .map_err(|error| CliError::Generic(error.to_string()))?; } + + if check_exit_code_one { + std::process::exit(1); + } else if check_mode { + println!("No formatting changes were detected"); + } + Ok(()) } diff --git a/tooling/nargo_cli/src/cli/fs/inputs.rs b/tooling/nargo_cli/src/cli/fs/inputs.rs index f3f0baf10f..023195010a 100644 --- a/tooling/nargo_cli/src/cli/fs/inputs.rs +++ b/tooling/nargo_cli/src/cli/fs/inputs.rs @@ -73,7 +73,7 @@ mod tests { use nargo::constants::VERIFIER_INPUT_FILE; use noirc_abi::{ input_parser::{Format, InputValue}, - Abi, AbiParameter, AbiType, AbiVisibility, + Abi, AbiParameter, AbiReturnType, AbiType, AbiVisibility, }; use tempfile::TempDir; @@ -98,7 +98,10 @@ mod tests { visibility: AbiVisibility::Private, }, ], - return_type: Some(AbiType::Field), + return_type: Some(AbiReturnType { + abi_type: AbiType::Field, + visibility: AbiVisibility::Public, + }), // Input serialization is only dependent on types, not position in witness map. // Neither of these should be relevant so we leave them empty. diff --git a/tooling/nargo_cli/src/cli/fs/program.rs b/tooling/nargo_cli/src/cli/fs/program.rs index e82f2d5526..807df25ba4 100644 --- a/tooling/nargo_cli/src/cli/fs/program.rs +++ b/tooling/nargo_cli/src/cli/fs/program.rs @@ -1,5 +1,6 @@ use std::path::{Path, PathBuf}; +use acvm::acir::circuit::Circuit; use nargo::artifacts::{ contract::PreprocessedContract, debug::DebugArtifact, program::PreprocessedProgram, }; @@ -18,6 +19,19 @@ pub(crate) fn save_program_to_file>( save_build_artifact_to_file(compiled_program, &circuit_name, circuit_dir) } +/// Writes the bytecode as acir.gz +pub(crate) fn only_acir>( + compiled_program: &PreprocessedProgram, + circuit_dir: P, +) -> PathBuf { + create_named_dir(circuit_dir.as_ref(), "target"); + let circuit_path = circuit_dir.as_ref().join("acir").with_extension("gz"); + let bytes = Circuit::serialize_circuit(&compiled_program.bytecode); + write_to_file(&bytes, &circuit_path); + + circuit_path +} + pub(crate) fn save_contract_to_file>( compiled_contract: &PreprocessedContract, circuit_name: &str, diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index b1cd5f0b64..b0f771bfc1 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -67,7 +67,7 @@ pub(crate) fn run( .cloned() .partition(|package| package.is_binary()); - let (np_language, opcode_support) = backend.get_backend_info()?; + let (np_language, opcode_support) = backend.get_backend_info_or_default(); let (compiled_programs, compiled_contracts) = compile_workspace( &workspace, &binary_packages, diff --git a/tooling/nargo_cli/src/cli/mod.rs b/tooling/nargo_cli/src/cli/mod.rs index 8d22fb1b20..88c6b57a98 100644 --- a/tooling/nargo_cli/src/cli/mod.rs +++ b/tooling/nargo_cli/src/cli/mod.rs @@ -60,7 +60,6 @@ pub(crate) struct NargoConfig { enum NargoCommand { Backend(backend_cmd::BackendCommand), Check(check_cmd::CheckCommand), - #[command(hide = true)] // Hidden while the feature has not been extensively tested Fmt(fmt_cmd::FormatCommand), CodegenVerifier(codegen_verifier_cmd::CodegenVerifierCommand), #[command(alias = "build")] diff --git a/tooling/nargo_cli/src/cli/prove_cmd.rs b/tooling/nargo_cli/src/cli/prove_cmd.rs index 3586e73ff2..54b148ec3a 100644 --- a/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -64,7 +64,7 @@ pub(crate) fn run( package, &args.compile_options, np_language, - &|opcode| opcode_support.is_opcode_supported(opcode), + &opcode_support, )?; prove_package( diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs index e117d8555a..43cfecd17e 100644 --- a/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -82,23 +82,40 @@ pub(crate) fn run( fn run_tests( blackbox_solver: &S, package: &Package, - test_name: FunctionNameMatch, + fn_name: FunctionNameMatch, show_output: bool, compile_options: &CompileOptions, ) -> Result<(), CliError> { - let (mut context, crate_id) = - prepare_package(package, Box::new(|path| std::fs::read_to_string(path))); + let (mut context, crate_id) = prepare_package(package); check_crate_and_report_errors( &mut context, crate_id, compile_options.deny_warnings, + compile_options.disable_macros, compile_options.silence_warnings, )?; - let test_functions = context.get_all_test_functions_in_crate_matching(&crate_id, test_name); + let test_functions = context.get_all_test_functions_in_crate_matching(&crate_id, fn_name); + let count_all = test_functions.len(); + if count_all == 0 { + return match &fn_name { + FunctionNameMatch::Anything => { + Err(CliError::Generic(format!("[{}] Found 0 tests.", package.name))) + } + FunctionNameMatch::Exact(pattern) => Err(CliError::Generic(format!( + "[{}] Found 0 tests matching input '{pattern}'.", + package.name + ))), + FunctionNameMatch::Contains(pattern) => Err(CliError::Generic(format!( + "[{}] Found 0 tests containing '{pattern}'.", + package.name + ))), + }; + } - println!("[{}] Running {} test functions", package.name, test_functions.len()); - let mut failing = 0; + let plural = if count_all == 1 { "" } else { "s" }; + println!("[{}] Running {count_all} test function{plural}", package.name); + let mut count_failed = 0; let writer = StandardStream::stderr(ColorChoice::Always); let mut writer = writer.lock(); @@ -116,13 +133,10 @@ fn run_tests( writeln!(writer, "ok").expect("Failed to write to stdout"); } TestStatus::Fail { message, error_diagnostic } => { - let writer = StandardStream::stderr(ColorChoice::Always); - let mut writer = writer.lock(); writer .set_color(ColorSpec::new().set_fg(Some(Color::Red))) .expect("Failed to set color"); - writeln!(writer, "{message}").expect("Failed to write to stdout"); - writer.reset().expect("Failed to reset writer"); + writeln!(writer, "{message}\n").expect("Failed to write to stdout"); if let Some(diag) = error_diagnostic { noirc_errors::reporter::report_all( context.file_manager.as_file_map(), @@ -131,7 +145,7 @@ fn run_tests( compile_options.silence_warnings, ); } - failing += 1; + count_failed += 1; } TestStatus::CompileError(err) => { noirc_errors::reporter::report_all( @@ -140,21 +154,37 @@ fn run_tests( compile_options.deny_warnings, compile_options.silence_warnings, ); - failing += 1; + count_failed += 1; } } writer.reset().expect("Failed to reset writer"); } - if failing == 0 { - write!(writer, "[{}] ", package.name).expect("Failed to write to stdout"); + write!(writer, "[{}] ", package.name).expect("Failed to write to stdout"); + + if count_failed == 0 { writer.set_color(ColorSpec::new().set_fg(Some(Color::Green))).expect("Failed to set color"); - writeln!(writer, "All tests passed").expect("Failed to write to stdout"); + writeln!(writer, "{count_all} test{plural} passed").expect("Failed to write to stdout"); + writer.reset().expect("Failed to reset writer"); + + Ok(()) } else { - let plural = if failing == 1 { "" } else { "s" }; - return Err(CliError::Generic(format!("[{}] {failing} test{plural} failed", package.name))); - } + let count_passed = count_all - count_failed; + let plural_failed = if count_failed == 1 { "" } else { "s" }; + let plural_passed = if count_passed == 1 { "" } else { "s" }; + + if count_passed != 0 { + writer + .set_color(ColorSpec::new().set_fg(Some(Color::Green))) + .expect("Failed to set color"); + write!(writer, "{count_passed} test{plural_passed} passed, ",) + .expect("Failed to write to stdout"); + } + writer.set_color(ColorSpec::new().set_fg(Some(Color::Red))).expect("Failed to set color"); + writeln!(writer, "{count_failed} test{plural_failed} failed") + .expect("Failed to write to stdout"); + writer.reset().expect("Failed to reset writer"); - writer.reset().expect("Failed to reset writer"); - Ok(()) + Err(CliError::Generic(String::new())) + } } diff --git a/tooling/nargo_cli/src/cli/verify_cmd.rs b/tooling/nargo_cli/src/cli/verify_cmd.rs index 8c6d92b3d2..2f8a6efbba 100644 --- a/tooling/nargo_cli/src/cli/verify_cmd.rs +++ b/tooling/nargo_cli/src/cli/verify_cmd.rs @@ -55,7 +55,7 @@ pub(crate) fn run( package, &args.compile_options, np_language, - &|opcode| opcode_support.is_opcode_supported(opcode), + &opcode_support, )?; verify_package(backend, &workspace, package, program, &args.verifier_name)?; diff --git a/tooling/nargo_cli/src/main.rs b/tooling/nargo_cli/src/main.rs index 92bd7b9498..7eeca2ab2b 100644 --- a/tooling/nargo_cli/src/main.rs +++ b/tooling/nargo_cli/src/main.rs @@ -11,11 +11,28 @@ mod backends; mod cli; mod errors; +use std::env; + use color_eyre::config::HookBuilder; +use env_logger::{Builder, Env}; +use tracing_appender::rolling; const PANIC_MESSAGE: &str = "This is a bug. We may have already fixed this in newer versions of Nargo so try searching for similar issues at https://github.com/noir-lang/noir/issues/.\nIf there isn't an open issue for this bug, consider opening one at https://github.com/noir-lang/noir/issues/new?labels=bug&template=bug_report.yml"; fn main() { + let env = Env::default().filter_or("NOIR_LOG", "error"); // Default to 'error' if NOIR_LOG is not set + Builder::from_env(env).init(); + + // Setup tracing + if let Ok(log_dir) = env::var("NARGO_LOG_DIR") { + let debug_file = rolling::daily(log_dir, "nargo-log"); + tracing_subscriber::fmt() + .with_writer(debug_file) + .with_ansi(false) + .with_max_level(tracing::Level::TRACE) + .init(); + } + // Register a panic hook to display more readable panic messages to end-users let (panic_hook, _) = HookBuilder::default().display_env_section(false).panic_section(PANIC_MESSAGE).into_hooks(); diff --git a/tooling/nargo_cli/tests/acir_artifacts/1327_concrete_in_generic/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/1327_concrete_in_generic/target/acir.gz deleted file mode 100644 index cc92863a4a..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/1327_concrete_in_generic/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/1327_concrete_in_generic/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/1327_concrete_in_generic/target/witness.gz deleted file mode 100644 index 454a9b75e0..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/1327_concrete_in_generic/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/1_mul/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/1_mul/target/acir.gz deleted file mode 100644 index 7572c9ac2c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/1_mul/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/1_mul/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/1_mul/target/witness.gz deleted file mode 100644 index 76f5c8a2fe..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/1_mul/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/2_div/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/2_div/target/acir.gz deleted file mode 100644 index 46405fc202..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/2_div/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/2_div/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/2_div/target/witness.gz deleted file mode 100644 index 3145b77d95..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/2_div/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/3_add/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/3_add/target/acir.gz deleted file mode 100644 index 42e66d90f7..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/3_add/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/3_add/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/3_add/target/witness.gz deleted file mode 100644 index 0cfc48c525..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/3_add/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/acir.gz deleted file mode 100644 index 633bec1356..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/witness.gz deleted file mode 100644 index 68e9df8078..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/5_over/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/5_over/target/acir.gz deleted file mode 100644 index 681a0290f7..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/5_over/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/5_over/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/5_over/target/witness.gz deleted file mode 100644 index b0a38188ca..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/5_over/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/6/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/6/target/acir.gz deleted file mode 100644 index 0cc489d893..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/6/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/6/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/6/target/witness.gz deleted file mode 100644 index 5c060e1b46..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/6/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/6_array/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/6_array/target/acir.gz deleted file mode 100644 index 787db190b4..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/6_array/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/6_array/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/6_array/target/witness.gz deleted file mode 100644 index cc96fd18e0..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/6_array/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/7/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/7/target/acir.gz deleted file mode 100644 index 7f14d2a932..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/7/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/7/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/7/target/witness.gz deleted file mode 100644 index d51356eb6c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/7/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/7_function/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/7_function/target/acir.gz deleted file mode 100644 index 5ddc1ba38e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/7_function/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/7_function/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/7_function/target/witness.gz deleted file mode 100644 index 0bb522d210..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/7_function/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/arithmetic_binary_operations/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/arithmetic_binary_operations/target/acir.gz deleted file mode 100644 index fd31cc3bfa..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/arithmetic_binary_operations/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/arithmetic_binary_operations/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/arithmetic_binary_operations/target/witness.gz deleted file mode 100644 index 450a83edc9..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/arithmetic_binary_operations/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/acir.gz deleted file mode 100644 index bb735d852d..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/witness.gz deleted file mode 100644 index b80b33eecd..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/array_eq/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/array_eq/target/acir.gz deleted file mode 100644 index b274cd7264..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_eq/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/array_eq/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/array_eq/target/witness.gz deleted file mode 100644 index f000e986c3..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_eq/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/array_len/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/array_len/target/acir.gz deleted file mode 100644 index 795d22712b..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_len/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/array_len/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/array_len/target/witness.gz deleted file mode 100644 index c3763958ee..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_len/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/array_neq/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/array_neq/target/acir.gz deleted file mode 100644 index 8d87f8bc57..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_neq/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/array_neq/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/array_neq/target/witness.gz deleted file mode 100644 index c56b373217..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_neq/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/array_sort/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/array_sort/target/acir.gz deleted file mode 100644 index 42d701ede8..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_sort/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/array_sort/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/array_sort/target/witness.gz deleted file mode 100644 index 8229809cc9..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_sort/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/assert/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/assert/target/acir.gz deleted file mode 100644 index c4e7f86f21..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/assert/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/assert/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/assert/target/witness.gz deleted file mode 100644 index 16880cedea..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/assert/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/assert_statement/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/assert_statement/target/acir.gz deleted file mode 100644 index d71ac1b6b0..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/assert_statement/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/assert_statement/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/assert_statement/target/witness.gz deleted file mode 100644 index 3e073aac63..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/assert_statement/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/assign_ex/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/assign_ex/target/acir.gz deleted file mode 100644 index a682df0b96..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/assign_ex/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/assign_ex/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/assign_ex/target/witness.gz deleted file mode 100644 index 35e05b7622..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/assign_ex/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bit_and/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/bit_and/target/acir.gz deleted file mode 100644 index 5fb7041cdf..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_and/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bit_and/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/bit_and/target/witness.gz deleted file mode 100644 index 0c5dc12cf1..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_and/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/acir.gz deleted file mode 100644 index 4756ea6b63..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/witness.gz deleted file mode 100644 index 890e987dd7..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/acir.gz deleted file mode 100644 index 45c1cc44c8..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/witness.gz deleted file mode 100644 index bdc4e70ba0..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bool_not/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/bool_not/target/acir.gz deleted file mode 100644 index 233a1e25f3..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bool_not/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bool_not/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/bool_not/target/witness.gz deleted file mode 100644 index 16880cedea..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bool_not/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bool_or/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/bool_or/target/acir.gz deleted file mode 100644 index 697832be20..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bool_or/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bool_or/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/bool_or/target/witness.gz deleted file mode 100644 index 10cffba714..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bool_or/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_acir_as_brillig/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_acir_as_brillig/target/acir.gz deleted file mode 100644 index 69cbde31d9..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_acir_as_brillig/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_acir_as_brillig/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_acir_as_brillig/target/witness.gz deleted file mode 100644 index 844178f043..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_acir_as_brillig/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_arrays/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_arrays/target/acir.gz deleted file mode 100644 index a093703d4b..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_arrays/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_arrays/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_arrays/target/witness.gz deleted file mode 100644 index 2d9b4cf245..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_arrays/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_assert/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_assert/target/acir.gz deleted file mode 100644 index 2cf3b7251e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_assert/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_assert/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_assert/target/witness.gz deleted file mode 100644 index 628e5fbc6d..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_assert/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_blake2s/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_blake2s/target/acir.gz deleted file mode 100644 index be47506c42..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_blake2s/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_blake2s/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_blake2s/target/witness.gz deleted file mode 100644 index d51356eb6c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_blake2s/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_calls/target/acir.gz deleted file mode 100644 index b69e231774..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_calls/target/witness.gz deleted file mode 100644 index 844178f043..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_array/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_array/target/acir.gz deleted file mode 100644 index 59b89c22bc..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_array/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_array/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_array/target/witness.gz deleted file mode 100644 index 266c94d043..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_array/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_conditionals/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_conditionals/target/acir.gz deleted file mode 100644 index e4155f58ea..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_conditionals/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_conditionals/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_conditionals/target/witness.gz deleted file mode 100644 index 3e7c051ffc..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_conditionals/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_conditional/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_conditional/target/acir.gz deleted file mode 100644 index 9117511d80..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_conditional/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_conditional/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_conditional/target/witness.gz deleted file mode 100644 index 162d33a5fd..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_conditional/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_ecdsa/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_ecdsa/target/acir.gz deleted file mode 100644 index cdc2851754..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_ecdsa/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_ecdsa/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_ecdsa/target/witness.gz deleted file mode 100644 index 5fe202b72f..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_ecdsa/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_fns_as_values/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_fns_as_values/target/acir.gz deleted file mode 100644 index d181921299..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_fns_as_values/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_fns_as_values/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_fns_as_values/target/witness.gz deleted file mode 100644 index f4a9c9f6dd..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_fns_as_values/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_hash_to_field/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_hash_to_field/target/acir.gz deleted file mode 100644 index 73c742a2dd..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_hash_to_field/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_hash_to_field/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_hash_to_field/target/witness.gz deleted file mode 100644 index 1529254d59..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_hash_to_field/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_identity_function/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_identity_function/target/acir.gz deleted file mode 100644 index 4e17ecc5d7..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_identity_function/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_identity_function/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_identity_function/target/witness.gz deleted file mode 100644 index 9a911d6251..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_identity_function/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_keccak/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_keccak/target/acir.gz deleted file mode 100644 index 1a64fd0398..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_keccak/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_keccak/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_keccak/target/witness.gz deleted file mode 100644 index 95b5064a5a..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_keccak/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_loop/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_loop/target/acir.gz deleted file mode 100644 index 04baae8d29..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_loop/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_loop/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_loop/target/witness.gz deleted file mode 100644 index 6e9e8ecd1d..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_loop/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_nested_arrays/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_nested_arrays/target/acir.gz deleted file mode 100644 index f69df4781e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_nested_arrays/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_nested_arrays/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_nested_arrays/target/witness.gz deleted file mode 100644 index 87cf83430f..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_nested_arrays/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_nested_slices/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_nested_slices/target/acir.gz deleted file mode 100644 index 100a208bcd..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_nested_slices/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_nested_slices/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_nested_slices/target/witness.gz deleted file mode 100644 index 3530c6f59c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_nested_slices/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_not/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_not/target/acir.gz deleted file mode 100644 index 9702ca340a..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_not/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_not/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_not/target/witness.gz deleted file mode 100644 index 3fbf07be37..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_not/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_oracle/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_oracle/target/acir.gz deleted file mode 100644 index db158f6188..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_oracle/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_oracle/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_oracle/target/witness.gz deleted file mode 100644 index 3fead7f6b2..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_oracle/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_pedersen/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_pedersen/target/acir.gz deleted file mode 100644 index 27f6f353d2..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_pedersen/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_pedersen/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_pedersen/target/witness.gz deleted file mode 100644 index b26110156a..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_pedersen/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_recursion/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_recursion/target/acir.gz deleted file mode 100644 index c0c91d8154..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_recursion/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_recursion/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_recursion/target/witness.gz deleted file mode 100644 index 46e192995f..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_recursion/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_references/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_references/target/acir.gz deleted file mode 100644 index 4069ca2cb5..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_references/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_references/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_references/target/witness.gz deleted file mode 100644 index bf62ea672e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_references/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_scalar_mul/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_scalar_mul/target/acir.gz deleted file mode 100644 index 9f5f787c65..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_scalar_mul/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_scalar_mul/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_scalar_mul/target/witness.gz deleted file mode 100644 index 3204207ec6..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_scalar_mul/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_schnorr/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_schnorr/target/acir.gz deleted file mode 100644 index 625ae64a11..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_schnorr/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_schnorr/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_schnorr/target/witness.gz deleted file mode 100644 index 17d93cc4d1..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_schnorr/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_sha256/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_sha256/target/acir.gz deleted file mode 100644 index 49f7e6afcf..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_sha256/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_sha256/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_sha256/target/witness.gz deleted file mode 100644 index 118042d584..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_sha256/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_slices/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_slices/target/acir.gz deleted file mode 100644 index 57ca1d59fe..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_slices/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_slices/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_slices/target/witness.gz deleted file mode 100644 index 3530c6f59c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_slices/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_to_be_bytes/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_to_be_bytes/target/acir.gz deleted file mode 100644 index 1249975b27..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_to_be_bytes/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_to_be_bytes/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_to_be_bytes/target/witness.gz deleted file mode 100644 index 0d48d54982..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_to_be_bytes/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_to_bytes_integration/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_to_bytes_integration/target/acir.gz deleted file mode 100644 index fe9ac34ed1..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_to_bytes_integration/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_to_bytes_integration/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_to_bytes_integration/target/witness.gz deleted file mode 100644 index b3813a1f97..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_to_bytes_integration/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_to_le_bytes/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_to_le_bytes/target/acir.gz deleted file mode 100644 index 834f57e1ee..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_to_le_bytes/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_to_le_bytes/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_to_le_bytes/target/witness.gz deleted file mode 100644 index d12168c557..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_to_le_bytes/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_top_level/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_top_level/target/acir.gz deleted file mode 100644 index 4b2fbcd346..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_top_level/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_top_level/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_top_level/target/witness.gz deleted file mode 100644 index 38bdf1f726..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_top_level/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_unitialised_arrays/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_unitialised_arrays/target/acir.gz deleted file mode 100644 index ac18684a07..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_unitialised_arrays/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_unitialised_arrays/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_unitialised_arrays/target/witness.gz deleted file mode 100644 index ceaf7ad008..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_unitialised_arrays/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/cast_bool/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/cast_bool/target/acir.gz deleted file mode 100644 index 032b36d162..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/cast_bool/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/cast_bool/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/cast_bool/target/witness.gz deleted file mode 100644 index fa79236ad5..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/cast_bool/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/closures_mut_ref/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/closures_mut_ref/target/acir.gz deleted file mode 100644 index 271b0ddd64..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/closures_mut_ref/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/closures_mut_ref/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/closures_mut_ref/target/witness.gz deleted file mode 100644 index 37c6d67fad..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/closures_mut_ref/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/acir.gz deleted file mode 100644 index 46a738a97e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/witness.gz deleted file mode 100644 index 5bafffff0d..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_2/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_2/target/acir.gz deleted file mode 100644 index 8b56f25b2c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_2/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_2/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_2/target/witness.gz deleted file mode 100644 index 310c2cba8c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_2/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_421/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_421/target/acir.gz deleted file mode 100644 index bb060b5ebc..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_421/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_421/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_421/target/witness.gz deleted file mode 100644 index 025b2d9ea4..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_421/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_661/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_661/target/acir.gz deleted file mode 100644 index 51e30b8bbc..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_661/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_661/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_661/target/witness.gz deleted file mode 100644 index 2683a9ba4a..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_661/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_short_circuit/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_short_circuit/target/acir.gz deleted file mode 100644 index 75f2bcfdb0..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_short_circuit/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_short_circuit/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_short_circuit/target/witness.gz deleted file mode 100644 index b2aa4a0b23..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_short_circuit/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_underflow/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_underflow/target/acir.gz deleted file mode 100644 index 6d43d0374b..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_underflow/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_underflow/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_underflow/target/witness.gz deleted file mode 100644 index 5b2d3b80af..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_underflow/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/custom_entry/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/custom_entry/target/acir.gz deleted file mode 100644 index c4e7f86f21..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/custom_entry/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/custom_entry/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/custom_entry/target/witness.gz deleted file mode 100644 index 16880cedea..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/custom_entry/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/debug_logs/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/debug_logs/target/acir.gz deleted file mode 100644 index ea9187f408..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/debug_logs/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/debug_logs/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/debug_logs/target/witness.gz deleted file mode 100644 index 3199dac092..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/debug_logs/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/diamond_deps_0/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/diamond_deps_0/target/acir.gz deleted file mode 100644 index e73668fd86..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/diamond_deps_0/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/diamond_deps_0/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/diamond_deps_0/target/witness.gz deleted file mode 100644 index d2a6bdba5c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/diamond_deps_0/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/distinct_keyword/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/distinct_keyword/target/acir.gz deleted file mode 100644 index b3411dc96a..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/distinct_keyword/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/distinct_keyword/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/distinct_keyword/target/witness.gz deleted file mode 100644 index d79dfba935..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/distinct_keyword/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/double_verify_proof/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/double_verify_proof/target/acir.gz deleted file mode 100644 index a2faad6514..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/double_verify_proof/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/double_verify_proof/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/double_verify_proof/target/witness.gz deleted file mode 100644 index 251984d629..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/double_verify_proof/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/ecdsa_secp256k1/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/ecdsa_secp256k1/target/acir.gz deleted file mode 100644 index 9108d663e8..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/ecdsa_secp256k1/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/ecdsa_secp256k1/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/ecdsa_secp256k1/target/witness.gz deleted file mode 100644 index a094ba3246..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/ecdsa_secp256k1/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/ecdsa_secp256r1/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/ecdsa_secp256r1/target/acir.gz deleted file mode 100644 index ec6bc2c73a..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/ecdsa_secp256r1/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/ecdsa_secp256r1/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/ecdsa_secp256r1/target/witness.gz deleted file mode 100644 index 79d009caea..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/ecdsa_secp256r1/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/acir.gz deleted file mode 100644 index b8577dbd3a..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/witness.gz deleted file mode 100644 index 7c125021d9..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/field_attribute/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/field_attribute/target/acir.gz deleted file mode 100644 index 9401237fd8..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/field_attribute/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/field_attribute/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/field_attribute/target/witness.gz deleted file mode 100644 index 5f3c241de5..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/field_attribute/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/generics/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/generics/target/acir.gz deleted file mode 100644 index c9462cfa87..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/generics/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/generics/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/generics/target/witness.gz deleted file mode 100644 index 4d120219b1..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/generics/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/global_consts/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/global_consts/target/acir.gz deleted file mode 100644 index 8b6a0d9db6..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/global_consts/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/global_consts/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/global_consts/target/witness.gz deleted file mode 100644 index 41fe927e80..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/global_consts/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/hash_to_field/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/hash_to_field/target/acir.gz deleted file mode 100644 index 9be98aef49..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/hash_to_field/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/hash_to_field/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/hash_to_field/target/witness.gz deleted file mode 100644 index 743d797096..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/hash_to_field/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/acir.gz deleted file mode 100644 index eab354be13..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/witness.gz deleted file mode 100644 index 329d15dfb1..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/if_else_chain/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/if_else_chain/target/acir.gz deleted file mode 100644 index 21cb3898a2..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/if_else_chain/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/if_else_chain/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/if_else_chain/target/witness.gz deleted file mode 100644 index 4ab0b124e7..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/if_else_chain/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/import/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/import/target/acir.gz deleted file mode 100644 index ff6e6f6c39..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/import/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/import/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/import/target/witness.gz deleted file mode 100644 index 93c5b96bdf..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/import/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/integer_array_indexing/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/integer_array_indexing/target/acir.gz deleted file mode 100644 index 1c4c50039e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/integer_array_indexing/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/integer_array_indexing/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/integer_array_indexing/target/witness.gz deleted file mode 100644 index b3d60e315e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/integer_array_indexing/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/keccak256/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/keccak256/target/acir.gz deleted file mode 100644 index cb74273e4d..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/keccak256/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/keccak256/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/keccak256/target/witness.gz deleted file mode 100644 index 42bcc0ccbd..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/keccak256/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/main_bool_arg/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/main_bool_arg/target/acir.gz deleted file mode 100644 index d054abe1df..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/main_bool_arg/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/main_bool_arg/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/main_bool_arg/target/witness.gz deleted file mode 100644 index 80a779d446..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/main_bool_arg/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/acir.gz deleted file mode 100644 index 75b1cbb507..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/witness.gz deleted file mode 100644 index 6351d29dd1..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/mock_oracle/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/mock_oracle/target/acir.gz deleted file mode 100644 index c45cd40f28..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/mock_oracle/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/mock_oracle/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/mock_oracle/target/witness.gz deleted file mode 100644 index 4e90289d5e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/mock_oracle/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/modules/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/modules/target/acir.gz deleted file mode 100644 index 05b5e23ae3..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/modules/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/modules/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/modules/target/witness.gz deleted file mode 100644 index 58c7b52ef8..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/modules/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/modules_more/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/modules_more/target/acir.gz deleted file mode 100644 index ff6e6f6c39..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/modules_more/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/modules_more/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/modules_more/target/witness.gz deleted file mode 100644 index 6f12eac202..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/modules_more/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/modulus/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/modulus/target/acir.gz deleted file mode 100644 index a99124a5e3..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/modulus/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/modulus/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/modulus/target/witness.gz deleted file mode 100644 index 02931c632f..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/modulus/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/acir.gz deleted file mode 100644 index 9f51852275..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/witness.gz deleted file mode 100644 index 62a1378dec..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/nested_arrays_from_brillig/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/nested_arrays_from_brillig/target/acir.gz deleted file mode 100644 index 270cfcaf53..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_arrays_from_brillig/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/nested_arrays_from_brillig/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/nested_arrays_from_brillig/target/witness.gz deleted file mode 100644 index a3161ac44f..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_arrays_from_brillig/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/acir.gz deleted file mode 100644 index 3db0a495a9..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/witness.gz deleted file mode 100644 index 9c9e80efe8..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/pedersen_check/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/pedersen_check/target/acir.gz deleted file mode 100644 index 02c9f32e3c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/pedersen_check/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/pedersen_check/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/pedersen_check/target/witness.gz deleted file mode 100644 index caf34e2b73..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/pedersen_check/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/poseidon_bn254_hash/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/poseidon_bn254_hash/target/acir.gz deleted file mode 100644 index 0327f60088..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/poseidon_bn254_hash/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/poseidon_bn254_hash/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/poseidon_bn254_hash/target/witness.gz deleted file mode 100644 index b3f3f1a3b2..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/poseidon_bn254_hash/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/poseidonsponge_x5_254/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/poseidonsponge_x5_254/target/acir.gz deleted file mode 100644 index dc260ce2aa..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/poseidonsponge_x5_254/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/poseidonsponge_x5_254/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/poseidonsponge_x5_254/target/witness.gz deleted file mode 100644 index f61ba4ec0c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/poseidonsponge_x5_254/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/pred_eq/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/pred_eq/target/acir.gz deleted file mode 100644 index 032b36d162..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/pred_eq/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/pred_eq/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/pred_eq/target/witness.gz deleted file mode 100644 index f1ea0249fe..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/pred_eq/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/references/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/references/target/acir.gz deleted file mode 100644 index 0668e2eca2..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/references/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/references/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/references/target/witness.gz deleted file mode 100644 index bf62ea672e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/references/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/regression/target/acir.gz deleted file mode 100644 index f92aa2603b..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/regression/target/witness.gz deleted file mode 100644 index dc1f8e0e3f..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression_2854/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/regression_2854/target/acir.gz deleted file mode 100644 index 6f4ffaa488..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression_2854/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression_2854/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/regression_2854/target/witness.gz deleted file mode 100644 index c0b900e811..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression_2854/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/acir.gz deleted file mode 100644 index 5c0339446c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/witness.gz deleted file mode 100644 index 095aef252e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression_method_cannot_be_found/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/regression_method_cannot_be_found/target/acir.gz deleted file mode 100644 index f29fbef8d3..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression_method_cannot_be_found/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression_method_cannot_be_found/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/regression_method_cannot_be_found/target/witness.gz deleted file mode 100644 index 4e90289d5e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression_method_cannot_be_found/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/scalar_mul/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/scalar_mul/target/acir.gz deleted file mode 100644 index 0bf8db7df7..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/scalar_mul/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/scalar_mul/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/scalar_mul/target/witness.gz deleted file mode 100644 index 637e61f60d..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/scalar_mul/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/acir.gz deleted file mode 100644 index 047e59422e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/witness.gz deleted file mode 100644 index 91bf1aeb7a..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/sha256/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/sha256/target/acir.gz deleted file mode 100644 index a2de8064bb..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/sha256/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/sha256/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/sha256/target/witness.gz deleted file mode 100644 index d5762dfc7d..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/sha256/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/acir.gz deleted file mode 100644 index 512a9089ac..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/witness.gz deleted file mode 100644 index 9450bf170e..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/acir.gz deleted file mode 100644 index 82747c1741..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/witness.gz deleted file mode 100644 index 6627fd7d53..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/acir.gz deleted file mode 100644 index 39a17a5a52..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/witness.gz deleted file mode 100644 index a35e3011ee..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_2d_array/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_2d_array/target/acir.gz deleted file mode 100644 index 59b62b9c99..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_2d_array/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_2d_array/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_2d_array/target/witness.gz deleted file mode 100644 index 321a76492d..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_2d_array/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_add_and_ret_arr/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_add_and_ret_arr/target/acir.gz deleted file mode 100644 index d7ec1ebc47..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_add_and_ret_arr/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_add_and_ret_arr/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_add_and_ret_arr/target/witness.gz deleted file mode 100644 index 35e05b7622..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_add_and_ret_arr/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_bitwise/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_bitwise/target/acir.gz deleted file mode 100644 index 84fc5cc5de..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_bitwise/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_bitwise/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_bitwise/target/witness.gz deleted file mode 100644 index 2afa317a12..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_bitwise/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_comparison/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_comparison/target/acir.gz deleted file mode 100644 index 452780c4d3..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_comparison/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_comparison/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_comparison/target/witness.gz deleted file mode 100644 index 5896584fa8..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_comparison/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_mut/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_mut/target/acir.gz deleted file mode 100644 index 9338b74aab..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_mut/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_mut/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_mut/target/witness.gz deleted file mode 100644 index 9e7641cea1..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_mut/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_not/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_not/target/acir.gz deleted file mode 100644 index a47defb9fe..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_not/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_not/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_not/target/witness.gz deleted file mode 100644 index a8e277ea79..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_not/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_print/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_print/target/acir.gz deleted file mode 100644 index 5a2c524f26..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_print/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_print/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_print/target/witness.gz deleted file mode 100644 index 35e05b7622..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_print/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_program_addition/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_program_addition/target/acir.gz deleted file mode 100644 index d7ec1ebc47..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_program_addition/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_program_addition/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_program_addition/target/witness.gz deleted file mode 100644 index 94ea8c8f2b..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_program_addition/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/acir.gz deleted file mode 100644 index 8c5fd3c0bd..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/witness.gz deleted file mode 100644 index 4b051d62ee..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/acir.gz deleted file mode 100644 index 1916c47591..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/witness.gz deleted file mode 100644 index 171330f514..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_shift_left_right/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_shift_left_right/target/acir.gz deleted file mode 100644 index 6bbdaef4a9..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_shift_left_right/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_shift_left_right/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_shift_left_right/target/witness.gz deleted file mode 100644 index 6f15adc652..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_shift_left_right/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/acir.gz deleted file mode 100644 index 7b605a2b87..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/witness.gz deleted file mode 100644 index 148355f933..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/slice_struct_field/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/slice_struct_field/target/acir.gz deleted file mode 100644 index 6b1f189a33..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slice_struct_field/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/slice_struct_field/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/slice_struct_field/target/witness.gz deleted file mode 100644 index f404e58ade..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slice_struct_field/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/slices/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/slices/target/acir.gz deleted file mode 100644 index 7a053fcb19..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slices/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/slices/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/slices/target/witness.gz deleted file mode 100644 index 359b2f7560..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slices/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/strings/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/strings/target/acir.gz deleted file mode 100644 index 424f4bd2d0..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/strings/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/strings/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/strings/target/witness.gz deleted file mode 100644 index 72a93aabbf..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/strings/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/struct/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/struct/target/acir.gz deleted file mode 100644 index e9de8adcb3..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/struct/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/struct/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/struct/target/witness.gz deleted file mode 100644 index a8e277ea79..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/struct/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/struct_array_inputs/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/struct_array_inputs/target/acir.gz deleted file mode 100644 index f66ed17a0c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/struct_array_inputs/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/struct_array_inputs/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/struct_array_inputs/target/witness.gz deleted file mode 100644 index 82307dcb96..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/struct_array_inputs/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/struct_fields_ordering/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/struct_fields_ordering/target/acir.gz deleted file mode 100644 index 8ddb62e879..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/struct_fields_ordering/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/struct_fields_ordering/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/struct_fields_ordering/target/witness.gz deleted file mode 100644 index e2eb314530..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/struct_fields_ordering/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/struct_inputs/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/struct_inputs/target/acir.gz deleted file mode 100644 index b658b4111f..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/struct_inputs/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/struct_inputs/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/struct_inputs/target/witness.gz deleted file mode 100644 index b52a864426..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/struct_inputs/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/submodules/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/submodules/target/acir.gz deleted file mode 100644 index 697832be20..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/submodules/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/submodules/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/submodules/target/witness.gz deleted file mode 100644 index 10cffba714..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/submodules/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/acir.gz deleted file mode 100644 index df6294bc97..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/witness.gz deleted file mode 100644 index b2ac9601ba..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/acir.gz deleted file mode 100644 index 2371186e8f..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/witness.gz deleted file mode 100644 index 610802628c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/acir.gz deleted file mode 100644 index 4deef489b9..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/witness.gz deleted file mode 100644 index 71d29209eb..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/acir.gz deleted file mode 100644 index 02d2bd105f..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/witness.gz deleted file mode 100644 index 610802628c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/trait_as_return_type/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/trait_as_return_type/target/acir.gz deleted file mode 100644 index 1d34f5beca..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/trait_as_return_type/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/trait_as_return_type/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/trait_as_return_type/target/witness.gz deleted file mode 100644 index c3b8e75866..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/trait_as_return_type/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/trait_impl_base_type/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/trait_impl_base_type/target/acir.gz deleted file mode 100644 index 531a1baf42..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/trait_impl_base_type/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/trait_impl_base_type/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/trait_impl_base_type/target/witness.gz deleted file mode 100644 index c3b8e75866..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/trait_impl_base_type/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/traits_in_crates_1/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/traits_in_crates_1/target/acir.gz deleted file mode 100644 index 6eb630ce2f..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/traits_in_crates_1/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/traits_in_crates_1/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/traits_in_crates_1/target/witness.gz deleted file mode 100644 index 60fc952646..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/traits_in_crates_1/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/traits_in_crates_2/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/traits_in_crates_2/target/acir.gz deleted file mode 100644 index 6eb630ce2f..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/traits_in_crates_2/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/traits_in_crates_2/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/traits_in_crates_2/target/witness.gz deleted file mode 100644 index 60fc952646..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/traits_in_crates_2/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/tuple_inputs/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/tuple_inputs/target/acir.gz deleted file mode 100644 index 79ae7dccb3..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/tuple_inputs/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/tuple_inputs/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/tuple_inputs/target/witness.gz deleted file mode 100644 index 0eb0d6f09f..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/tuple_inputs/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/tuples/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/tuples/target/acir.gz deleted file mode 100644 index a053f565e5..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/tuples/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/tuples/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/tuples/target/witness.gz deleted file mode 100644 index 10cffba714..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/tuples/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/type_aliases/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/type_aliases/target/acir.gz deleted file mode 100644 index 7855747826..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/type_aliases/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/type_aliases/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/type_aliases/target/witness.gz deleted file mode 100644 index 8137a9d31c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/type_aliases/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/xor/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/xor/target/acir.gz deleted file mode 100644 index eda28c748c..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/xor/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/xor/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/xor/target/witness.gz deleted file mode 100644 index 444c8e01cd..0000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/xor/target/witness.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/compile_failure/no_nested_impl/src/main.nr b/tooling/nargo_cli/tests/compile_failure/no_nested_impl/src/main.nr deleted file mode 100644 index 916567a7c0..0000000000 --- a/tooling/nargo_cli/tests/compile_failure/no_nested_impl/src/main.nr +++ /dev/null @@ -1,21 +0,0 @@ -fn main() { - let a: [[[[Field; 2]; 2]; 2]; 2] = [[[[1, 2], [3, 4]], [[5, 6], [7, 8]]], [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]]; - assert(a.eq(a)); -} - -trait Eq { - fn eq(self, other: Self) -> bool; -} - -impl Eq for [T; 2] where T: Eq { - fn eq(self, other: Self) -> bool { - self[0].eq(other[0]) - & self[0].eq(other[0]) - } -} -// Impl for u32 but not Field -impl Eq for u32 { - fn eq(self, other: Self) -> bool { - self == other - } -} diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/a/src/main.nr b/tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/a/src/main.nr deleted file mode 100644 index 550e5034a7..0000000000 --- a/tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/a/src/main.nr +++ /dev/null @@ -1,3 +0,0 @@ -fn main(x : Field, y : pub Field) { - assert(x == y); -} diff --git a/tooling/nargo_cli/tests/compile_success_contract/simple_contract/src/main.nr b/tooling/nargo_cli/tests/compile_success_contract/simple_contract/src/main.nr deleted file mode 100644 index 88edd4ac2c..0000000000 --- a/tooling/nargo_cli/tests/compile_success_contract/simple_contract/src/main.nr +++ /dev/null @@ -1,14 +0,0 @@ -contract Foo { - fn double(x: Field) -> pub Field { - x * 2 - } - fn triple(x: Field) -> pub Field { - x * 3 - } - internal fn quadruple(x: Field) -> pub Field { - x * 4 - } - open internal fn skibbidy(x: Field) -> pub Field { - x * 5 - } -} diff --git a/tooling/nargo_cli/tests/compile_success_empty/ec_baby_jubjub/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/ec_baby_jubjub/src/main.nr deleted file mode 100644 index e7f3299945..0000000000 --- a/tooling/nargo_cli/tests/compile_success_empty/ec_baby_jubjub/src/main.nr +++ /dev/null @@ -1,174 +0,0 @@ -// Tests may be checked against https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/tree/main/poc -use dep::std::ec::tecurve::affine::Curve as AffineCurve; -use dep::std::ec::tecurve::affine::Point as Gaffine; -use dep::std::ec::tecurve::curvegroup::Curve; -use dep::std::ec::tecurve::curvegroup::Point as G; - -use dep::std::ec::swcurve::affine::Point as SWGaffine; -use dep::std::ec::swcurve::curvegroup::Point as SWG; - -use dep::std::ec::montcurve::affine::Point as MGaffine; -use dep::std::ec::montcurve::curvegroup::Point as MG; - -fn main() { - // This test only makes sense if Field is the right prime field. - if 21888242871839275222246405745257275088548364400416034343698204186575808495617 == 0 { - // Define Baby Jubjub (ERC-2494) parameters in affine representation - let bjj_affine = AffineCurve::new(168700, - 168696, - Gaffine::new(995203441582195749578291179787384436505546430278305826713579947235728471134, - 5472060717959818805561601436314318772137091100104008585924551046643952123905)); - // Test addition - let p1_affine = Gaffine::new(17777552123799933955779906779655732241715742912184938656739573121738514868268, - 2626589144620713026669568689430873010625803728049924121243784502389097019475); - let p2_affine = Gaffine::new(16540640123574156134436876038791482806971768689494387082833631921987005038935, - 20819045374670962167435360035096875258406992893633759881276124905556507972311); - - let p3_affine = bjj_affine.add(p1_affine, p2_affine); - assert(p3_affine.eq(Gaffine::new(7916061937171219682591368294088513039687205273691143098332585753343424131937, - 14035240266687799601661095864649209771790948434046947201833777492504781204499))); - // Test scalar multiplication - let p4_affine = bjj_affine.mul(2, p1_affine); - assert(p4_affine.eq(Gaffine::new(6890855772600357754907169075114257697580319025794532037257385534741338397365, - 4338620300185947561074059802482547481416142213883829469920100239455078257889))); - assert(p4_affine.eq(bjj_affine.bit_mul([0, 1], p1_affine))); - // Test subtraction - let p5_affine = bjj_affine.subtract(p3_affine, p3_affine); - assert(p5_affine.eq(Gaffine::zero())); - // Check that these points are on the curve - assert(bjj_affine.contains(bjj_affine.gen) - & bjj_affine.contains(p1_affine) - & bjj_affine.contains(p2_affine) - & bjj_affine.contains(p3_affine) - & bjj_affine.contains(p4_affine) - & bjj_affine.contains(p5_affine)); - // Test CurveGroup equivalents - let bjj = bjj_affine.into_group(); // Baby Jubjub - let p1 = p1_affine.into_group(); - let p2 = p2_affine.into_group(); - let p3 = p3_affine.into_group(); - let p4 = p4_affine.into_group(); - let p5 = p5_affine.into_group(); - // Test addition - assert(p3.eq(bjj.add(p1, p2))); - // Test scalar multiplication - assert(p4.eq(bjj.mul(2, p1))); - assert(p4.eq(bjj.bit_mul([0, 1], p1))); - // Test subtraction - assert(G::zero().eq(bjj.subtract(p3, p3))); - assert(p5.eq(G::zero())); - // Check that these points are on the curve - assert(bjj.contains(bjj.gen) - & bjj.contains(p1) - & bjj.contains(p2) - & bjj.contains(p3) - & bjj.contains(p4) - & bjj.contains(p5)); - // Test SWCurve equivalents of the above - // First the affine representation - let bjj_swcurve_affine = bjj_affine.into_swcurve(); - - let p1_swcurve_affine = bjj_affine.map_into_swcurve(p1_affine); - let p2_swcurve_affine = bjj_affine.map_into_swcurve(p2_affine); - let p3_swcurve_affine = bjj_affine.map_into_swcurve(p3_affine); - let p4_swcurve_affine = bjj_affine.map_into_swcurve(p4_affine); - let p5_swcurve_affine = bjj_affine.map_into_swcurve(p5_affine); - // Addition - assert(p3_swcurve_affine.eq(bjj_swcurve_affine.add(p1_swcurve_affine, p2_swcurve_affine))); - // Doubling - assert(p4_swcurve_affine.eq(bjj_swcurve_affine.mul(2, p1_swcurve_affine))); - assert(p4_swcurve_affine.eq(bjj_swcurve_affine.bit_mul([0, 1], p1_swcurve_affine))); - // Subtraction - assert(SWGaffine::zero().eq(bjj_swcurve_affine.subtract(p3_swcurve_affine, p3_swcurve_affine))); - assert(p5_swcurve_affine.eq(SWGaffine::zero())); - // Check that these points are on the curve - assert(bjj_swcurve_affine.contains(bjj_swcurve_affine.gen) - & bjj_swcurve_affine.contains(p1_swcurve_affine) - & bjj_swcurve_affine.contains(p2_swcurve_affine) - & bjj_swcurve_affine.contains(p3_swcurve_affine) - & bjj_swcurve_affine.contains(p4_swcurve_affine) - & bjj_swcurve_affine.contains(p5_swcurve_affine)); - // Then the CurveGroup representation - let bjj_swcurve = bjj.into_swcurve(); - - let p1_swcurve = bjj.map_into_swcurve(p1); - let p2_swcurve = bjj.map_into_swcurve(p2); - let p3_swcurve = bjj.map_into_swcurve(p3); - let p4_swcurve = bjj.map_into_swcurve(p4); - let p5_swcurve = bjj.map_into_swcurve(p5); - // Addition - assert(p3_swcurve.eq(bjj_swcurve.add(p1_swcurve, p2_swcurve))); - // Doubling - assert(p4_swcurve.eq(bjj_swcurve.mul(2, p1_swcurve))); - assert(p4_swcurve.eq(bjj_swcurve.bit_mul([0, 1], p1_swcurve))); - // Subtraction - assert(SWG::zero().eq(bjj_swcurve.subtract(p3_swcurve, p3_swcurve))); - assert(p5_swcurve.eq(SWG::zero())); - // Check that these points are on the curve - assert(bjj_swcurve.contains(bjj_swcurve.gen) - & bjj_swcurve.contains(p1_swcurve) - & bjj_swcurve.contains(p2_swcurve) - & bjj_swcurve.contains(p3_swcurve) - & bjj_swcurve.contains(p4_swcurve) - & bjj_swcurve.contains(p5_swcurve)); - // Test MontCurve conversions - // First the affine representation - let bjj_montcurve_affine = bjj_affine.into_montcurve(); - - let p1_montcurve_affine = p1_affine.into_montcurve(); - let p2_montcurve_affine = p2_affine.into_montcurve(); - let p3_montcurve_affine = p3_affine.into_montcurve(); - let p4_montcurve_affine = p4_affine.into_montcurve(); - let p5_montcurve_affine = p5_affine.into_montcurve(); - // Addition - assert(p3_montcurve_affine.eq(bjj_montcurve_affine.add(p1_montcurve_affine, p2_montcurve_affine))); - // Doubling - assert(p4_montcurve_affine.eq(bjj_montcurve_affine.mul(2, p1_montcurve_affine))); - assert(p4_montcurve_affine.eq(bjj_montcurve_affine.bit_mul([0, 1], p1_montcurve_affine))); - // Subtraction - assert(MGaffine::zero().eq(bjj_montcurve_affine.subtract(p3_montcurve_affine, p3_montcurve_affine))); - assert(p5_montcurve_affine.eq(MGaffine::zero())); - // Check that these points are on the curve - assert(bjj_montcurve_affine.contains(bjj_montcurve_affine.gen) - & bjj_montcurve_affine.contains(p1_montcurve_affine) - & bjj_montcurve_affine.contains(p2_montcurve_affine) - & bjj_montcurve_affine.contains(p3_montcurve_affine) - & bjj_montcurve_affine.contains(p4_montcurve_affine) - & bjj_montcurve_affine.contains(p5_montcurve_affine)); - // Then the CurveGroup representation - let bjj_montcurve = bjj.into_montcurve(); - - let p1_montcurve = p1_montcurve_affine.into_group(); - let p2_montcurve = p2_montcurve_affine.into_group(); - let p3_montcurve = p3_montcurve_affine.into_group(); - let p4_montcurve = p4_montcurve_affine.into_group(); - let p5_montcurve = p5_montcurve_affine.into_group(); - // Addition - assert(p3_montcurve.eq(bjj_montcurve.add(p1_montcurve, p2_montcurve))); - // Doubling - assert(p4_montcurve.eq(bjj_montcurve.mul(2, p1_montcurve))); - assert(p4_montcurve.eq(bjj_montcurve.bit_mul([0, 1], p1_montcurve))); - // Subtraction - assert(MG::zero().eq(bjj_montcurve.subtract(p3_montcurve, p3_montcurve))); - assert(p5_montcurve.eq(MG::zero())); - // Check that these points are on the curve - assert(bjj_montcurve.contains(bjj_montcurve.gen) - & bjj_montcurve.contains(p1_montcurve) - & bjj_montcurve.contains(p2_montcurve) - & bjj_montcurve.contains(p3_montcurve) - & bjj_montcurve.contains(p4_montcurve) - & bjj_montcurve.contains(p5_montcurve)); - // Elligator 2 map-to-curve - let ell2_pt_map = bjj_affine.elligator2_map(27); - - assert(ell2_pt_map.eq(MGaffine::new(7972459279704486422145701269802978968072470631857513331988813812334797879121, - 8142420778878030219043334189293412482212146646099536952861607542822144507872).into_tecurve())); - // SWU map-to-curve - let swu_pt_map = bjj_affine.swu_map(5, 27); - - assert(swu_pt_map.eq(bjj_affine.map_from_swcurve( - SWGaffine::new(2162719247815120009132293839392097468339661471129795280520343931405114293888, - 5341392251743377373758788728206293080122949448990104760111875914082289313973) - ))); - } -} diff --git a/tooling/nargo_cli/tests/compile_success_empty/regression_2099/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/regression_2099/src/main.nr deleted file mode 100644 index 185a6426cb..0000000000 --- a/tooling/nargo_cli/tests/compile_success_empty/regression_2099/src/main.nr +++ /dev/null @@ -1,34 +0,0 @@ -use dep::std::ec::tecurve::affine::Curve as AffineCurve; -use dep::std::ec::tecurve::affine::Point as Gaffine; -use dep::std::ec::tecurve::curvegroup::Curve; -use dep::std::ec::tecurve::curvegroup::Point as G; - -use dep::std::ec::swcurve::affine::Point as SWGaffine; -use dep::std::ec::swcurve::curvegroup::Point as SWG; - -use dep::std::ec::montcurve::affine::Point as MGaffine; -use dep::std::ec::montcurve::curvegroup::Point as MG; - -fn main() { - // Define Baby Jubjub (ERC-2494) parameters in affine representation - let bjj_affine = AffineCurve::new(168700, - 168696, - Gaffine::new(995203441582195749578291179787384436505546430278305826713579947235728471134, - 5472060717959818805561601436314318772137091100104008585924551046643952123905)); - // Test addition - let p1_affine = Gaffine::new(17777552123799933955779906779655732241715742912184938656739573121738514868268, - 2626589144620713026669568689430873010625803728049924121243784502389097019475); - let p2_affine = Gaffine::new(16540640123574156134436876038791482806971768689494387082833631921987005038935, - 20819045374670962167435360035096875258406992893633759881276124905556507972311); - let _p3_affine = bjj_affine.add(p1_affine, p2_affine); - // Test SWCurve equivalents of the above - // First the affine representation - let bjj_swcurve_affine = bjj_affine.into_swcurve(); - - let p1_swcurve_affine = bjj_affine.map_into_swcurve(p1_affine); - let p2_swcurve_affine = bjj_affine.map_into_swcurve(p2_affine); - - let _p3_swcurve_affine_from_add = bjj_swcurve_affine.add(p1_swcurve_affine, p2_swcurve_affine); - // Check that these points are on the curve - assert(bjj_swcurve_affine.contains(p1_swcurve_affine)); -} diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_static_methods/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/trait_static_methods/src/main.nr deleted file mode 100644 index 0150da6831..0000000000 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_static_methods/src/main.nr +++ /dev/null @@ -1,41 +0,0 @@ -trait ATrait { - fn asd() -> Self; - - fn static_method() -> Field { - Self::static_method_2() - } - - fn static_method_2() -> Field { - 100 - } -} - -struct Foo { - x: Field -} -impl ATrait for Foo { - fn asd() -> Self { - // This should pass as Self should be bound to Foo while typechecking this - Foo{x: 100} - } -} - -struct Bar { - x: Field -} -impl ATrait for Bar { - // The trait method is declared as returning `Self` - // but explicitly specifying the type in the impl should work - fn asd() -> Bar { - Bar{x: 100} - } - - fn static_method_2() -> Field { - 200 - } -} - -fn main() { - assert(Foo::static_method() == 100); - assert(Bar::static_method() == 200); -} diff --git a/tooling/nargo_cli/tests/execution_success/1_mul/Nargo.toml b/tooling/nargo_cli/tests/execution_success/1_mul/Nargo.toml deleted file mode 100644 index a0fd8d9802..0000000000 --- a/tooling/nargo_cli/tests/execution_success/1_mul/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "1_mul" -type = "bin" -authors = [""] - -[dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/array_dynamic/src/main.nr b/tooling/nargo_cli/tests/execution_success/array_dynamic/src/main.nr deleted file mode 100644 index 9e21334e51..0000000000 --- a/tooling/nargo_cli/tests/execution_success/array_dynamic/src/main.nr +++ /dev/null @@ -1,30 +0,0 @@ -fn main(x: [u32; 5], mut z: u32, t: u32, index: [Field;5], index2: [Field;5], offset: Field, sublen: Field) { - let idx = (z - 5 * t - 5) as Field; - //dynamic array test - dyn_array(x, idx, idx - 3); - //regression for issue 1283 - let mut s = 0; - let x3 = [246, 159, 32, 176, 8]; - for i in 0..5 { - s += x3[index[i]]; - } - assert(s != 0); - - if 3 < (sublen as u32) { - assert(index[offset + 3] == index2[3]); - } -} - -fn dyn_array(mut x: [u32; 5], y: Field, z: Field) { - assert(x[y] == 111); - assert(x[z] == 101); - x[z] = 0; - assert(x[y] == 111); - assert(x[1] == 0); - if y as u32 < 10 { - x[y] = x[y] - 2; - } else { - x[y] = 0; - } - assert(x[4] == 109); -} diff --git a/tooling/nargo_cli/tests/execution_success/bit_shifts_comptime/src/main.nr b/tooling/nargo_cli/tests/execution_success/bit_shifts_comptime/src/main.nr deleted file mode 100644 index 8afed4c1e1..0000000000 --- a/tooling/nargo_cli/tests/execution_success/bit_shifts_comptime/src/main.nr +++ /dev/null @@ -1,21 +0,0 @@ -fn main(x: u64) { - let two: u64 = 2; - let three: u64 = 3; - // shifts on constant values - assert(two << 2 == 8); - assert((two << 3) / 8 == two); - assert((three >> 1) == 1); - // shifts on runtime values - assert(x << 1 == 128); - assert(x >> 2 == 16); - - regression_2250(); -} - -fn regression_2250() { - let a: u1 = 1 >> 1; - assert(a == 0); - - let b: u32 = 1 >> 32; - assert(b == 0); -} diff --git a/tooling/nargo_cli/tests/execution_success/brillig_oracle/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_oracle/src/main.nr deleted file mode 100644 index 86cf6ff149..0000000000 --- a/tooling/nargo_cli/tests/execution_success/brillig_oracle/src/main.nr +++ /dev/null @@ -1,26 +0,0 @@ -use dep::std::slice; -// Tests oracle usage in brillig/unconstrained functions -fn main(x: Field) { - get_number_sequence_wrapper(20); -} -// TODO(#1911): This function does not need to be an oracle but acts -// as a useful test while we finalize code generation for slices in Brillig -#[oracle(get_number_sequence)] -unconstrained fn get_number_sequence(_size: Field) -> [Field] {} -// TODO(#1911) -#[oracle(get_reverse_number_sequence)] -unconstrained fn get_reverse_number_sequence(_size: Field) -> [Field] {} - -unconstrained fn get_number_sequence_wrapper(size: Field) { - let slice = get_number_sequence(size); - for i in 0..19 as u32 { - assert(slice[i] == i as Field); - } - - let reversed_slice = get_reverse_number_sequence(size); - // Regression test that we have not overwritten memory - for i in 0..19 as u32 { - assert(slice[i] == reversed_slice[19 - i]); - } -} - diff --git a/tooling/nargo_cli/tests/execution_success/brillig_scalar_mul/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_scalar_mul/src/main.nr deleted file mode 100644 index 30c51ce0f5..0000000000 --- a/tooling/nargo_cli/tests/execution_success/brillig_scalar_mul/src/main.nr +++ /dev/null @@ -1,16 +0,0 @@ -use dep::std; - -unconstrained fn main(a: Field, a_pub_x: pub Field, a_pub_y: pub Field, b: Field, b_pub_x: pub Field, b_pub_y: pub Field) { - let mut priv_key = a; - let mut pub_x: Field = a_pub_x; - let mut pub_y: Field = a_pub_y; - if a != 1 { - // Change `a` in Prover.toml to test input `b` - priv_key = b; - pub_x = b_pub_x; - pub_y = b_pub_y; - } - let res = std::scalar_mul::fixed_base_embedded_curve(priv_key, 0); - assert(res[0] == pub_x); - assert(res[1] == pub_y); -} diff --git a/tooling/nargo_cli/tests/execution_success/brillig_schnorr/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_schnorr/src/main.nr deleted file mode 100644 index 107b311f6a..0000000000 --- a/tooling/nargo_cli/tests/execution_success/brillig_schnorr/src/main.nr +++ /dev/null @@ -1,19 +0,0 @@ -use dep::std; -// Note: If main has any unsized types, then the verifier will never be able -// to figure out the circuit instance -unconstrained fn main(message: [u8; 10], message_field: Field, pub_key_x: Field, pub_key_y: Field, signature: [u8; 64]) { - // Regression for issue #2421 - // We want to make sure that we can accurately verify a signature whose message is a slice vs. an array - let message_field_bytes = message_field.to_be_bytes(10); - for i in 0..10 { - assert(message[i] == message_field_bytes[i]); - } - // Is there ever a situation where someone would want - // to ensure that a signature was invalid? - // Check that passing a slice as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message_field_bytes); - assert(valid_signature); - // Check that passing an array as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message); - assert(valid_signature); -} diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/src/main.nr b/tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/src/main.nr deleted file mode 100644 index be70b67be5..0000000000 --- a/tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/src/main.nr +++ /dev/null @@ -1,15 +0,0 @@ -// Regression test for https://github.com/noir-lang/noir/issues/3493 -fn main(x: u4) { - if x == 10 { - x + 15; - } - if x == 9 { - x << 3; - } - if x == 8 { - x * 3; - } - if x == 7 { - x - 8; - } -} \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/double_verify_proof/src/main.nr b/tooling/nargo_cli/tests/execution_success/double_verify_proof/src/main.nr deleted file mode 100644 index ecc00bbd56..0000000000 --- a/tooling/nargo_cli/tests/execution_success/double_verify_proof/src/main.nr +++ /dev/null @@ -1,28 +0,0 @@ -use dep::std; - -fn main( - verification_key: [Field; 114], - proof: [Field; 94], - public_inputs: [Field; 1], - key_hash: Field, - input_aggregation_object: [Field; 16], - proof_b: [Field; 94] -) -> pub [Field; 16] { - let output_aggregation_object_a = std::verify_proof(verification_key.as_slice(), - proof.as_slice(), - public_inputs.as_slice(), - key_hash, - input_aggregation_object); - - let output_aggregation_object = std::verify_proof(verification_key.as_slice(), - proof_b.as_slice(), - public_inputs.as_slice(), - key_hash, - output_aggregation_object_a); - - let mut output = [0; 16]; - for i in 0..16 { - output[i] = output_aggregation_object[i]; - } - output -} diff --git a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/src/main.nr b/tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/src/main.nr deleted file mode 100644 index 552fcea9af..0000000000 --- a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/src/main.nr +++ /dev/null @@ -1,10 +0,0 @@ -use dep::std; - -fn main(message: [u8;38], hashed_message: [u8;32], pub_key_x: [u8;32], pub_key_y: [u8;32], signature: [u8;64]) { - // Hash the message, since secp256k1 expects a hashed_message - let expected = std::hash::sha256(message); - assert(hashed_message == expected); - - let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); -} diff --git a/tooling/nargo_cli/tests/execution_success/higher_order_functions/src/main.nr b/tooling/nargo_cli/tests/execution_success/higher_order_functions/src/main.nr deleted file mode 100644 index 479cdbbe7b..0000000000 --- a/tooling/nargo_cli/tests/execution_success/higher_order_functions/src/main.nr +++ /dev/null @@ -1,97 +0,0 @@ -fn main(w: Field) -> pub Field { - let f = if 3 * 7 > 200 as u32 { foo } else { bar }; - assert(f()[1] == 2); - // Lambdas: - assert(twice(|x| x * 2, 5) == 20); - assert((|x, y| x + y + 1)(2, 3) == 6); - // nested lambdas - assert((|a, b| { - a + (|c| c + 2)(b) - })(0, 1) - == 3); - // Closures: - let a = 42; - let g = || a; - assert(g() == 42); - // When you copy mutable variables, - // the capture of the copies shouldn't change: - let mut x = 2; - x = x + 1; - let z = x; - // Add extra mutations to ensure we can mutate x without the - // captured z changing. - x = x + 1; - assert((|y| y + z)(1) == 4); - // When you capture mutable variables, - // again, the captured variable doesn't change: - let closure_capturing_mutable = (|y| y + x); - assert(closure_capturing_mutable(1) == 5); - x += 1; - assert(closure_capturing_mutable(1) == 5); - - regression_2154(); - - let ret = twice(add1, 3); - - test_array_functions(); - w + ret -} -/// Test the array functions in std::array -fn test_array_functions() { - let two = 2; // giving this a name, to ensure that the Option functions work with closures - let myarray: [i32; 3] = [1, 2, 3]; - assert(myarray.any(|n| n > 2)); - assert(myarray.any(|n| n > two)); - - let evens: [i32; 3] = myarray.map(|n| n * two); // [2, 4, 6] - assert(evens.all(|n| n > 1)); - assert(evens.all(|n| n >= two)); - - assert(evens.fold(0, |a, b| a + b) == 12); - assert(evens.fold(0, |a, b| a + b + two) == 18); - assert(evens.reduce(|a, b| a + b) == 12); - assert(evens.reduce(|a, b| a + b + two) == 16); - // TODO: is this a sort_via issue with the new backend, - // or something more general? - // - // currently it fails only with `--experimental-ssa` with - // "not yet implemented: Cast into signed" - // but it worked with the original ssa backend - // (before dropping it) - // - // opened #2121 for it - // https://github.com/noir-lang/noir/issues/2121 - // let descending = myarray.sort_via(|a, b| a > b); - // assert(descending == [3, 2, 1]); - assert(evens.map(|n| n / 2) == myarray); - assert(evens.map(|n| n / two) == myarray); -} - -fn foo() -> [u32; 2] { - [1, 3] -} - -fn bar() -> [u32; 2] { - [3, 2] -} - -fn add1(x: Field) -> Field { - x + 1 -} - -fn twice(f: fn(Field) -> Field, x: Field) -> Field { - f(f(x)) -} -// Fixing an ICE, where rewriting the closures -// during monomorphization didn't correspond -// to an internal `if` type -// found by @jfecher: -// https://github.com/noir-lang/noir/pull/1959#issuecomment-1658992989 -// issue https://github.com/noir-lang/noir/issues/2154 -fn regression_2154() { - let x: u32 = 32; - - let closure_if_else = if x > 2 { || x } else { || x + 2342 }; - - assert(closure_if_else() == 32); -} diff --git a/tooling/nargo_cli/tests/execution_success/prelude/Nargo.toml b/tooling/nargo_cli/tests/execution_success/prelude/Nargo.toml new file mode 100644 index 0000000000..35f223bce0 --- /dev/null +++ b/tooling/nargo_cli/tests/execution_success/prelude/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "prelude" +type = "bin" +authors = [""] +compiler_version = ">=0.20.0" + +[dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/prelude/src/main.nr b/tooling/nargo_cli/tests/execution_success/prelude/src/main.nr new file mode 100644 index 0000000000..9bf2ec18f3 --- /dev/null +++ b/tooling/nargo_cli/tests/execution_success/prelude/src/main.nr @@ -0,0 +1,32 @@ +fn main(x: Field, y: pub Field) { + let xs = Vec::new(); + let option = Option::none(); + + print("42\n"); + println("42"); +} + +mod a { + // We don't want to give an error due to re-importing elements that are already in the prelude. + use dep::std::collections::vec::Vec; + use dep::std::option::Option; + use dep::{print, println}; + + fn main() { + let xs = Vec::new(); + let option = Option::none(); + + print("42\n"); + println("42"); + } +} + +mod b { + fn main() { + let xs = Vec::new(); + let option = Option::none(); + + print("42\n"); + println("42"); + } +} diff --git a/tooling/nargo_cli/tests/execution_success/regression/src/main.nr b/tooling/nargo_cli/tests/execution_success/regression/src/main.nr deleted file mode 100644 index ed3dbf23a2..0000000000 --- a/tooling/nargo_cli/tests/execution_success/regression/src/main.nr +++ /dev/null @@ -1,107 +0,0 @@ -global NIBBLE_LENGTH: Field = 16; - -fn compact_decode(input: [u8; N], length: Field) -> ([u4; NIBBLE_LENGTH], Field) { - assert(2 * input.len() as u64 <= NIBBLE_LENGTH as u64); - assert(length as u64 <= input.len() as u64); - - let mut nibble = [0 as u4; NIBBLE_LENGTH]; - - let first_nibble = (input[0] >> 4) as u4; - let parity = first_nibble as u1; - - if parity == 1 { - nibble[0] = (input[0] & 0x0f) as u4; - for i in 1..input.len() { - if i as u64 < length as u64 { - let x = input[i]; - nibble[2*i - 1] = (x >> 4) as u4; - nibble[2*i] = (x & 0x0f) as u4; - } - } - } else { - for i in 0..2 { - if (i as u64) < length as u64 - 1 { - let x = input[i + 1]; - nibble[2*i] = (x >> 4) as u4; - nibble[2*i + 1] = (x & 0x0f) as u4; - } - } - } - - let out = (nibble, 2 * length + (parity as Field) - 2); - - out -} - -fn enc(value: [u8; N], value_length: Field) -> ([u8; 32], Field) { - assert(value.len() as u8 >= value_length as u8); - let mut out_value = [0; 32]; - if value_length == 0 { - let out = (out_value, value_length); - out - } else if value_length as u8 < 31 { - out_value[0] = 0x80 + value_length as u8; - - for i in 1..value.len() { - out_value[i] = value[i-1]; - } - - let out = (out_value, value_length + 1); - - out - } else { - let out = (out_value, 32); - out - } -} - -fn bitshift_literal_0() -> u64 { - let mut bits: u64 = 0; - bits |= 1 << 0; - - bits -} -fn bitshift_literal_4() -> u64 { - let mut bits: u64 = 0; - bits |= 1 << 4; - - bits -} -fn bitshift_variable(idx: u64) -> u64 { - let mut bits: u64 = 0; - bits |= 1 << idx; - - bits -} - -fn main(x: [u8; 5], z: Field) { - //Issue 1144 - let (nib, len) = compact_decode(x, z); - assert(len == 5); - assert([nib[0], nib[1], nib[2], nib[3], nib[4]] == [15, 1, 12, 11, 8]); - // Issue 1169 - let val1 = [ - 0xb8, 0x8f, 0x61, 0xe6, 0xfb, 0xda, 0x83, 0xfb, 0xff, 0xfa, 0xbe, 0x36, 0x41, 0x12, 0x13, - 0x74, 0x80, 0x39, 0x80, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 - ]; - let val1_length = 20; - - let enc_val1 = enc(val1, val1_length); - - assert(enc_val1.0 == [ - 0x94, 0xb8, 0x8f, 0x61, 0xe6, 0xfb, 0xda, 0x83, 0xfb, 0xff, 0xfa, 0xbe, 0x36, 0x41, - 0x12, 0x13, 0x74, 0x80, 0x39, 0x80, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 - ]); - assert(enc_val1.1 == 21); - // Issue 2399 - let result_0 = bitshift_literal_0(); - assert(result_0 == 1); - let result_4 = bitshift_literal_4(); - assert(result_4 == 16); - let result_0 = bitshift_variable(0); - assert(result_0 == 1); - let result_4 = bitshift_variable(4); - assert(result_4 == 16); -} diff --git a/tooling/nargo_cli/tests/execution_success/scalar_mul/src/main.nr b/tooling/nargo_cli/tests/execution_success/scalar_mul/src/main.nr deleted file mode 100644 index 4f0a83ea9e..0000000000 --- a/tooling/nargo_cli/tests/execution_success/scalar_mul/src/main.nr +++ /dev/null @@ -1,16 +0,0 @@ -use dep::std; - -fn main(a: Field, a_pub_x: pub Field, a_pub_y: pub Field, b: Field, b_pub_x: pub Field, b_pub_y: pub Field) { - let mut priv_key = a; - let mut pub_x: Field = a_pub_x; - let mut pub_y: Field = a_pub_y; - if a != 1 { - // Change `a` in Prover.toml to test input `b` - priv_key = b; - pub_x = b_pub_x; - pub_y = b_pub_y; - } - let res = std::scalar_mul::fixed_base_embedded_curve(priv_key, 0); - assert(res[0] == pub_x); - assert(res[1] == pub_y); -} diff --git a/tooling/nargo_cli/tests/execution_success/schnorr/src/main.nr b/tooling/nargo_cli/tests/execution_success/schnorr/src/main.nr deleted file mode 100644 index d5eb92fd5f..0000000000 --- a/tooling/nargo_cli/tests/execution_success/schnorr/src/main.nr +++ /dev/null @@ -1,19 +0,0 @@ -use dep::std; -// Note: If main has any unsized types, then the verifier will never be able -// to figure out the circuit instance -fn main(message: [u8; 10], message_field: Field, pub_key_x: Field, pub_key_y: Field, signature: [u8; 64]) { - // Regression for issue #2421 - // We want to make sure that we can accurately verify a signature whose message is a slice vs. an array - let message_field_bytes = message_field.to_be_bytes(10); - for i in 0..10 { - assert(message[i] == message_field_bytes[i]); - } - // Is there ever a situation where someone would want - // to ensure that a signature was invalid? - // Check that passing a slice as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message_field_bytes); - assert(valid_signature); - // Check that passing an array as the message is valid - let valid_signature = std::schnorr::verify_signature(pub_key_x, pub_key_y, signature, message); - assert(valid_signature); -} diff --git a/tooling/nargo_cli/tests/execution_success/simple_print/Prover.toml b/tooling/nargo_cli/tests/execution_success/simple_print/Prover.toml deleted file mode 100644 index 2c1854573a..0000000000 --- a/tooling/nargo_cli/tests/execution_success/simple_print/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = 1 -y = 2 diff --git a/tooling/nargo_cli/tests/execution_success/slice_dynamic_index/src/main.nr b/tooling/nargo_cli/tests/execution_success/slice_dynamic_index/src/main.nr deleted file mode 100644 index 2e5c0122df..0000000000 --- a/tooling/nargo_cli/tests/execution_success/slice_dynamic_index/src/main.nr +++ /dev/null @@ -1,308 +0,0 @@ -fn main(x: Field) { - // The parameters to this function must come directly from witness values (inputs to main). - regression_dynamic_slice_index(x - 1, x - 4); -} - -fn regression_dynamic_slice_index(x: Field, y: Field) { - let mut slice = []; - for i in 0..5 { - slice = slice.push_back(i); - } - assert(slice.len() == 5); - - dynamic_slice_index_set_if(slice, x, y); - dynamic_slice_index_set_else(slice, x, y); - dynamic_slice_index_set_nested_if_else_else(slice, x, y); - dynamic_slice_index_set_nested_if_else_if(slice, x, y + 1); - dynamic_slice_index_if(slice, x); - dynamic_array_index_if([0, 1, 2, 3, 4], x); - dynamic_slice_index_else(slice, x); - - dynamic_slice_merge_if(slice, x); - dynamic_slice_merge_else(slice, x); - dynamic_slice_merge_two_ifs(slice, x); - dynamic_slice_merge_mutate_between_ifs(slice, x, y); - dynamic_slice_merge_push_then_pop(slice, x, y); -} - -fn dynamic_slice_index_set_if(mut slice: [Field], x: Field, y: Field) { - assert(slice[x] == 4); - assert(slice[y] == 1); - slice[y] = 0; - assert(slice[x] == 4); - assert(slice[1] == 0); - if x as u32 < 10 { - assert(slice[x] == 4); - slice[x] = slice[x] - 2; - slice[x - 1] = slice[x]; - } else { - slice[x] = 0; - } - assert(slice[3] == 2); - assert(slice[4] == 2); -} - -fn dynamic_slice_index_set_else(mut slice: [Field], x: Field, y: Field) { - assert(slice[x] == 4); - assert(slice[y] == 1); - slice[y] = 0; - assert(slice[x] == 4); - assert(slice[1] == 0); - if x as u32 > 10 { - assert(slice[x] == 4); - slice[x] = slice[x] - 2; - slice[x - 1] = slice[x]; - } else { - slice[x] = 0; - } - assert(slice[4] == 0); -} -// This tests the case of missing a store instruction in the else branch -// of merging slices -fn dynamic_slice_index_if(mut slice: [Field], x: Field) { - if x as u32 < 10 { - assert(slice[x] == 4); - slice[x] = slice[x] - 2; - } else { - assert(slice[x] == 0); - } - assert(slice[4] == 2); -} - -fn dynamic_array_index_if(mut array: [Field; 5], x: Field) { - if x as u32 < 10 { - assert(array[x] == 4); - array[x] = array[x] - 2; - } else { - assert(array[x] == 0); - } - assert(array[4] == 2); -} -// This tests the case of missing a store instruction in the then branch -// of merging slices -fn dynamic_slice_index_else(mut slice: [Field], x: Field) { - if x as u32 > 10 { - assert(slice[x] == 0); - } else { - assert(slice[x] == 4); - slice[x] = slice[x] - 2; - } - assert(slice[4] == 2); -} - -fn dynamic_slice_merge_if(mut slice: [Field], x: Field) { - if x as u32 < 10 { - assert(slice[x] == 4); - slice[x] = slice[x] - 2; - - slice = slice.push_back(10); - // Having an array set here checks whether we appropriately - // handle a slice length that is not yet resolving to a constant - // during flattening - slice[x] = 10; - assert(slice[slice.len() - 1] == 10); - assert(slice.len() == 6); - - slice[x] = 20; - slice[x] = slice[x] + 10; - - slice = slice.push_front(11); - assert(slice[0] == 11); - assert(slice.len() == 7); - assert(slice[5] == 30); - - slice = slice.push_front(12); - assert(slice[0] == 12); - assert(slice.len() == 8); - assert(slice[6] == 30); - - let (popped_slice, last_elem) = slice.pop_back(); - assert(last_elem == 10); - assert(popped_slice.len() == 7); - - let (first_elem, rest_of_slice) = popped_slice.pop_front(); - assert(first_elem == 12); - assert(rest_of_slice.len() == 6); - // TODO(#2462): SliceInsert and SliceRemove with a dynamic index are not yet implemented in ACIR gen - slice = rest_of_slice.insert(2, 20); - assert(slice[2] == 20); - assert(slice[6] == 30); - assert(slice.len() == 7); - // TODO(#2462): SliceInsert and SliceRemove with a dynamic index are not yet implemented in ACIR gen - let (removed_slice, removed_elem) = slice.remove(3); - // The deconstructed tuple assigns to the slice but is not seen outside of the if statement - // without a direct assignment - slice = removed_slice; - - assert(removed_elem == 1); - assert(slice.len() == 6); - } else { - assert(slice[x] == 0); - slice = slice.push_back(20); - } - - assert(slice.len() == 6); - assert(slice[slice.len() - 1] == 30); -} - -fn dynamic_slice_merge_else(mut slice: [Field], x: Field) { - if x as u32 > 10 { - assert(slice[x] == 0); - slice[x] = 2; - } else { - assert(slice[x] == 4); - slice[x] = slice[x] - 2; - slice = slice.push_back(10); - } - assert(slice.len() == 6); - assert(slice[slice.len() - 1] == 10); - - slice = slice.push_back(20); - assert(slice.len() == 7); - assert(slice[slice.len() - 1] == 20); -} - -fn dynamic_slice_index_set_nested_if_else_else(mut slice: [Field], x: Field, y: Field) { - assert(slice[x] == 4); - assert(slice[y] == 1); - slice[y] = 0; - assert(slice[x] == 4); - assert(slice[1] == 0); - if x as u32 < 10 { - slice[x] = slice[x] - 2; - if y != 1 { - slice[x] = slice[x] + 20; - } else { - if x == 5 { - // We should not hit this case - assert(slice[x] == 22); - } else { - slice[x] = 10; - slice = slice.push_back(15); - assert(slice.len() == 6); - } - assert(slice[4] == 10); - } - } else { - slice[x] = 0; - } - assert(slice[4] == 10); - assert(slice.len() == 6); - assert(slice[slice.len() - 1] == 15); - - slice = slice.push_back(20); - assert(slice.len() == 7); - assert(slice[slice.len() - 1] == 20); -} - -fn dynamic_slice_index_set_nested_if_else_if(mut slice: [Field], x: Field, y: Field) { - assert(slice[x] == 4); - assert(slice[y] == 2); - slice[y] = 0; - assert(slice[x] == 4); - assert(slice[2] == 0); - if x as u32 < 10 { - slice[x] = slice[x] - 2; - // TODO: this panics as we have a load for the slice in flattening - if y == 1 { - slice[x] = slice[x] + 20; - } else { - if x == 4 { - slice[x] = 5; - } - assert(slice[4] == 5); - } - } else { - slice[x] = 0; - } - assert(slice[4] == 5); -} - -fn dynamic_slice_merge_two_ifs(mut slice: [Field], x: Field) { - if x as u32 > 10 { - assert(slice[x] == 0); - slice[x] = 2; - } else { - assert(slice[x] == 4); - slice[x] = slice[x] - 2; - slice = slice.push_back(10); - } - - assert(slice.len() == 6); - assert(slice[slice.len() - 1] == 10); - - if x == 20 { - slice = slice.push_back(20); - } - - slice = slice.push_back(15); - - assert(slice.len() == 7); - assert(slice[slice.len() - 1] == 15); - - slice = slice.push_back(20); - assert(slice.len() == 8); - assert(slice[slice.len() - 1] == 20); -} - -fn dynamic_slice_merge_mutate_between_ifs(mut slice: [Field], x: Field, y: Field) { - if x != y { - slice[x] = 50; - slice = slice.push_back(y); - slice = slice.push_back(x); - } else { - slice[x] = slice[x] - 2; - slice = slice.push_back(x); - } - - slice = slice.push_back(30); - assert(slice.len() == 8); - - if x == 20 { - slice = slice.push_back(20); - } - - slice = slice.push_back(15); - - if x != 20 { - slice = slice.push_back(50); - } - - slice = slice.push_back(60); - assert(slice.len() == 11); - assert(slice[x] == 50); - assert(slice[slice.len() - 4] == 30); - assert(slice[slice.len() - 3] == 15); - assert(slice[slice.len() - 2] == 50); - assert(slice[slice.len() - 1] == 60); -} - -fn dynamic_slice_merge_push_then_pop(mut slice: [Field], x: Field, y: Field) { - if x != y { - slice[x] = 5; - slice = slice.push_back(y); - slice = slice.push_back(x); - assert(slice.len() == 7); - - let (popped_slice, elem) = slice.pop_back(); - assert(slice.len() == 7); - assert(elem == x); - slice = popped_slice; - } else { - slice = slice.push_back(x); - } - - slice = slice.push_back(30); - assert(slice.len() == 7); - - if x == 20 { - slice = slice.push_back(20); - } - - let (slice, elem) = slice.pop_back(); - assert(elem == 30); - - let (_, elem) = slice.pop_back(); - assert(elem == y); -} - diff --git a/tooling/nargo_cli/tests/execution_success/slice_struct_field/src/main.nr b/tooling/nargo_cli/tests/execution_success/slice_struct_field/src/main.nr deleted file mode 100644 index c00fdf8518..0000000000 --- a/tooling/nargo_cli/tests/execution_success/slice_struct_field/src/main.nr +++ /dev/null @@ -1,177 +0,0 @@ -struct FooParent { - parent_arr: [Field; 3], - foos: [Foo], -} - -struct Bar { - inner: [Field; 3], -} - -struct Foo { - a: Field, - b: [Field], - bar: Bar, -} - -fn main(y: pub Field) { - let mut b_one = [2, 3, 20]; - b_one = b_one.push_back(20); - let foo_one = Foo { a: 1, b: b_one, bar: Bar { inner: [100, 101, 102] } }; - - let mut b_two = [5, 6, 21]; - b_two = b_two.push_back(21); - let foo_two = Foo { a: 4, b: b_two, bar: Bar { inner: [103, 104, 105] } }; - - let foo_three = Foo { a: 7, b: [8, 9, 22], bar: Bar { inner: [106, 107, 108] } }; - let foo_four = Foo { a: 10, b: [11, 12, 23], bar: Bar { inner: [109, 110, 111] } }; - - let mut x = [foo_one, foo_two]; - x = x.push_back(foo_three); - x = x.push_back(foo_four); - - assert(x[y - 3].a == 1); - let struct_slice = x[y - 3].b; - for i in 0..4 { - assert(struct_slice[i] == b_one[i]); - } - - assert(x[y - 2].a == 4); - let struct_slice = x[y - 2].b; - for i in 0..4 { - assert(struct_slice[i] == b_two[i]); - } - - assert(x[y - 1].a == 7); - let struct_slice = x[y - 1].b; - assert(struct_slice[0] == 8); - assert(struct_slice[1] == 9); - assert(struct_slice[2] == 22); - - assert(x[y].a == 10); - let struct_slice = x[y].b; - assert(struct_slice[0] == 11); - assert(struct_slice[1] == 12); - assert(struct_slice[2] == 23); - assert(x[y].bar.inner == [109, 110, 111]); - - assert(x[y - 3].bar.inner == [100, 101, 102]); - assert(x[y - 2].bar.inner == [103, 104, 105]); - assert(x[y - 1].bar.inner == [106, 107, 108]); - assert(x[y].bar.inner == [109, 110, 111]); - // Check that switching the lhs and rhs is still valid - assert([109, 110, 111] == x[y].bar.inner); - // TODO: Enable merging nested slices - // if y != 2 { - // x[y].a = 50; - // } else { - // x[y].a = 100; - // } - // assert(x[3].a == 50); - // if y == 2 { - // x[y - 1].b = [50, 51, 52]; - // } else { - // x[y - 1].b = [100, 101, 102]; - // } - // assert(x[2].b[0] == 100); - // assert(x[2].b[1] == 101); - // assert(x[2].b[2] == 102); - let q = x.push_back(foo_four); - let foo_parent_one = FooParent { parent_arr: [0, 1, 2], foos: x }; - let foo_parent_two = FooParent { parent_arr: [3, 4, 5], foos: q }; - let mut foo_parents = [foo_parent_one]; - foo_parents = foo_parents.push_back(foo_parent_two); - // TODO: make a separate test for compile time - // foo_parents[1].foos.push_back(foo_four); - // TODO: Merging nested slices is broken - // if y == 3 { - // foo_parents[y - 2].foos[y - 1].b[y - 1] = 5000; - // } else { - // foo_parents[y - 2].foos[y - 1].b[y - 1] = 1000; - // } - assert(foo_parents[y - 2].foos[y - 2].b[y - 1] == 21); - foo_parents[y - 2].foos[y - 2].b[y - 1] = 5000; - assert(foo_parents[y - 2].foos[y - 2].b[y - 1] == 5000); - - let b_array = foo_parents[y - 2].foos[y - 3].b; - assert(foo_parents[y - 2].foos[y - 3].a == 1); - assert(b_array[0] == 2); - assert(b_array[1] == 3); - assert(b_array[2] == 20); - assert(b_array[3] == 20); - - let b_array = foo_parents[y - 2].foos[y - 2].b; - assert(foo_parents[y - 2].foos[y - 2].a == 4); - assert(b_array[0] == 5); - assert(b_array[1] == 6); - assert(b_array[2] == 5000); - assert(b_array[3] == 21); - - assert(foo_parents[y - 2].foos[y - 1].a == 7); - foo_parents[y - 2].foos[y - 1].a = 50; - - let b_array = foo_parents[y - 2].foos[y - 1].b; - assert(b_array[2] == 22); - assert(b_array.len() == 3); - // Test setting a nested array with non-dynamic - let x = [5, 6, 5000, 21, 100, 101].as_slice(); - foo_parents[y - 2].foos[y - 1].b = x; - - assert(foo_parents[y - 2].foos[y - 1].b.len() == 6); - assert(foo_parents[y - 2].foos[y - 1].b[4] == 100); - assert(foo_parents[y - 2].foos[y - 1].b[5] == 101); - - test_basic_intrinsics_nested_slices(foo_parents, y); - // TODO(#3364): still have to enable slice intrinsics on dynamic nested slices - // assert(foo_parents[y - 2].foos.len() == 5); - // foo_parents[y - 2].foos = foo_parents[y - 2].foos.push_back(foo_four); - // assert(foo_parents[y - 2].foos.len() == 6); - let b_array = foo_parents[y - 2].foos[y - 1].b; - assert(b_array[0] == 5); - assert(b_array[1] == 6); - assert(b_array[2] == 5000); - assert(b_array[3] == 21); - - let b_array = foo_parents[y - 2].foos[y].b; - assert(foo_parents[y - 2].foos[y].a == 10); - assert(b_array[0] == 11); - assert(b_array[1] == 12); - assert(b_array[2] == 23); - - assert(foo_parents[y - 2].foos[y - 3].bar.inner == [100, 101, 102]); - assert(foo_parents[y - 2].foos[y - 2].bar.inner == [103, 104, 105]); - assert(foo_parents[y - 2].foos[y - 1].bar.inner == [106, 107, 108]); - assert(foo_parents[y - 2].foos[y].bar.inner == [109, 110, 111]); -} - -fn test_basic_intrinsics_nested_slices(mut foo_parents: [FooParent], y: Field) { - foo_parents[y - 2].foos[y - 1].b = foo_parents[y - 2].foos[y - 1].b.push_back(500); - assert(foo_parents[y - 2].foos[y - 1].b.len() == 7); - assert(foo_parents[y - 2].foos[y - 1].b[6] == 500); - - let (popped_slice, last_elem) = foo_parents[y - 2].foos[y - 1].b.pop_back(); - foo_parents[y - 2].foos[y - 1].b = popped_slice; - assert(foo_parents[y - 2].foos[y - 1].b.len() == 6); - assert(last_elem == 500); - - foo_parents[y - 2].foos[y - 1].b = foo_parents[y - 2].foos[y - 1].b.push_front(11); - assert(foo_parents[y - 2].foos[y - 1].b.len() == 7); - assert(foo_parents[y - 2].foos[y - 1].b[0] == 11); - - let (first_elem, rest_of_slice) = foo_parents[y - 2].foos[y - 1].b.pop_front(); - foo_parents[y - 2].foos[y - 1].b = rest_of_slice; - assert(foo_parents[y - 2].foos[y - 1].b.len() == 6); - assert(first_elem == 11); - - foo_parents[y - 2].foos[y - 1].b = foo_parents[y - 2].foos[y - 1].b.insert(2, 20); - assert(foo_parents[y - 2].foos[y - 1].b.len() == 7); - assert(foo_parents[y - 2].foos[y - 1].b[y - 1] == 20); - assert(foo_parents[y - 2].foos[y - 1].b[y] == 5000); - assert(foo_parents[y - 2].foos[y - 1].b[6] == 101); - - let (rest_of_slice, removed_elem) = foo_parents[y - 2].foos[y - 1].b.remove(3); - foo_parents[y - 2].foos[y - 1].b = rest_of_slice; - assert(removed_elem == 5000); - assert(foo_parents[y - 2].foos[y - 1].b.len() == 6); - assert(foo_parents[y - 2].foos[y - 1].b[2] == 20); - assert(foo_parents[y - 2].foos[y - 1].b[3] == 21); -} diff --git a/tooling/nargo_cli/tests/execution_success/strings/src/main.nr b/tooling/nargo_cli/tests/execution_success/strings/src/main.nr deleted file mode 100644 index cb2218837f..0000000000 --- a/tooling/nargo_cli/tests/execution_success/strings/src/main.nr +++ /dev/null @@ -1,73 +0,0 @@ -use dep::std; -// Test global string literals -global HELLO_WORLD = "hello world"; - -fn main(message: pub str<11>, y: Field, hex_as_string: str<4>, hex_as_field: Field) { - let mut bad_message = "hello world"; - - assert(message == "hello world"); - assert(message == HELLO_WORLD); - let x = 10; - let z = x * 5; - std::println(10); - - std::println(z); // x * 5 in println not yet supported - std::println(x); - - let array = [1, 2, 3, 5, 8]; - assert(y == 5); // Change to y != 5 to see how the later print statements are not called - std::println(array); - - bad_message = "hell\0\"world"; - std::println(bad_message); - assert(message != bad_message); - - let hash = std::hash::pedersen_commitment([x]); - std::println(hash); - - assert(hex_as_string == "0x41"); - // assert(hex_as_string != 0x41); This will fail with a type mismatch between str[4] and Field - assert(hex_as_field == 0x41); -} - -#[test] -fn test_prints_strings() { - let message = "hello world!"; - - std::println(message); - std::println("goodbye world"); -} - -#[test] -fn test_prints_array() { - let array = [1, 2, 3, 5, 8]; - - let s = Test { a: 1, b: 2, c: [3, 4] }; - std::println(s); - - std::println(array); - - let hash = std::hash::pedersen_commitment(array); - std::println(hash); -} - -fn failed_constraint(hex_as_field: Field) { - // TODO(#2116): Note that `println` will not work if a failed constraint can be - // evaluated at compile time. - // When this method is called from a test method or with constant values - // a `Failed constraint` compile error will be caught before this `println` - // is executed as the input will be a constant. - std::println(hex_as_field); - assert(hex_as_field != 0x41); -} - -#[test] -fn test_failed_constraint() { - failed_constraint(0x41); -} - -struct Test { - a: Field, - b: Field, - c: [Field; 2], -} diff --git a/tooling/nargo_cli/tests/execution_success/workspace_default_member/b/src/main.nr b/tooling/nargo_cli/tests/execution_success/workspace_default_member/b/src/main.nr deleted file mode 100644 index 6e170de75f..0000000000 --- a/tooling/nargo_cli/tests/execution_success/workspace_default_member/b/src/main.nr +++ /dev/null @@ -1,3 +0,0 @@ -fn main(x : Field, y : pub Field) { - assert(x != y); -} diff --git a/tooling/nargo_cli/tests/rebuild.sh b/tooling/nargo_cli/tests/rebuild.sh deleted file mode 100755 index d89402fb1c..0000000000 --- a/tooling/nargo_cli/tests/rebuild.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -set -e - -excluded_dirs=("workspace" "workspace_default_member") - -current_dir=$(pwd) -base_path="$current_dir/execution_success" - -# Clear the acir_artifacts directory of any existing artifacts -rm -rf $current_dir/acir_artifacts -mkdir -p $current_dir/acir_artifacts - -# Loop over every directory -for dir in $base_path/*; do - if [[ ! -d $dir ]]; then - continue - fi - - dir_name=$(basename "$dir") - - if [[ ! " ${excluded_dirs[@]} " =~ " ${dir_name} " ]]; then - if [[ ! -d "$current_dir/acir_artifacts/$dir_name" ]]; then - mkdir -p $current_dir/acir_artifacts/$dir_name - fi - - cd $dir - if [ -d ./target/ ]; then - rm -r ./target/ - fi - nargo compile && nargo execute witness - - # Rename witness.tr to witness.gz - if [ -f ./target/witness.tr ]; then - mv ./target/witness.tr ./target/witness.gz - fi - - # Extract bytecode field from JSON, base64 decode it, and save it to the target directory - if [ -f ./target/${dir_name}.json ]; then - jq -r '.bytecode' ./target/${dir_name}.json | base64 -d > ./target/acir.gz - fi - - # Delete the JSON file after extracting bytecode field - rm ./target/${dir_name}.json - - # Clear the target directory in acir_artifacts - if [ -d "$current_dir/acir_artifacts/$dir_name/target" ]; then - rm -r "$current_dir/acir_artifacts/$dir_name/target" - fi - mkdir $current_dir/acir_artifacts/$dir_name/target - - # Move the artifacts from the target directory to the corresponding directory in acir_artifacts - mv ./target/*.gz $current_dir/acir_artifacts/$dir_name/target/ - - cd $base_path - fi -done diff --git a/tooling/nargo_fmt/Cargo.toml b/tooling/nargo_fmt/Cargo.toml index 921c9893ab..374413ac9f 100644 --- a/tooling/nargo_fmt/Cargo.toml +++ b/tooling/nargo_fmt/Cargo.toml @@ -13,4 +13,4 @@ toml.workspace = true thiserror.workspace = true [dev-dependencies] -similar-asserts = "1.5.0" +similar-asserts.workspace = true diff --git a/tooling/nargo_fmt/build.rs b/tooling/nargo_fmt/build.rs index cd93866ece..c356b403ae 100644 --- a/tooling/nargo_fmt/build.rs +++ b/tooling/nargo_fmt/build.rs @@ -46,8 +46,8 @@ fn generate_formatter_tests(test_file: &mut File, test_data_dir: &Path) { .collect::>() .join("\n"); - let output_source_path = outputs_dir.join(file_name); - let output_source = std::fs::read_to_string(output_source_path).unwrap(); + let output_source_path = outputs_dir.join(file_name).display().to_string(); + let output_source = std::fs::read_to_string(output_source_path.clone()).unwrap(); write!( test_file, @@ -58,11 +58,14 @@ fn format_{test_name}() {{ let expected_output = r#"{output_source}"#; - let (parsed_module, errors) = noirc_frontend::parse_program(&input); + let (parsed_module, _errors) = noirc_frontend::parse_program(&input); let config = nargo_fmt::Config::of("{config}").unwrap(); let fmt_text = nargo_fmt::format(&input, parsed_module, &config); + if std::env::var("UPDATE_EXPECT").is_ok() {{ + std::fs::write("{output_source_path}", fmt_text.clone()).unwrap(); + }} similar_asserts::assert_eq!(fmt_text, expected_output); }} diff --git a/tooling/nargo_fmt/src/rewrite.rs b/tooling/nargo_fmt/src/rewrite.rs index c1ac585985..6a95eba875 100644 --- a/tooling/nargo_fmt/src/rewrite.rs +++ b/tooling/nargo_fmt/src/rewrite.rs @@ -1,5 +1,11 @@ mod array; +mod expr; mod infix; +mod parenthesized; +mod typ; pub(crate) use array::rewrite as array; +pub(crate) use expr::{rewrite as expr, rewrite_sub_expr as sub_expr}; pub(crate) use infix::rewrite as infix; +pub(crate) use parenthesized::rewrite as parenthesized; +pub(crate) use typ::rewrite as typ; diff --git a/tooling/nargo_fmt/src/rewrite/array.rs b/tooling/nargo_fmt/src/rewrite/array.rs index 9c49d82752..fc5b240f83 100644 --- a/tooling/nargo_fmt/src/rewrite/array.rs +++ b/tooling/nargo_fmt/src/rewrite/array.rs @@ -2,7 +2,7 @@ use noirc_frontend::{hir::resolution::errors::Span, token::Token, Expression}; use crate::{ utils::{Expr, FindToken}, - visitor::FmtVisitor, + visitor::{expr::NewlineMode, FmtVisitor}, }; pub(crate) fn rewrite(mut visitor: FmtVisitor, array: Vec, array_span: Span) -> String { @@ -26,7 +26,7 @@ pub(crate) fn rewrite(mut visitor: FmtVisitor, array: Vec, array_spa let end = item_span.start(); let leading = visitor.slice(start..end).trim_matches(pattern); - let item = visitor.format_sub_expr(item); + let item = super::sub_expr(&visitor, visitor.shape(), item); let next_start = items.peek().map_or(end_position, |expr| expr.span.start()); let trailing = visitor.slice(item_span.end()..next_start); let offset = trailing @@ -80,6 +80,6 @@ pub(crate) fn rewrite(mut visitor: FmtVisitor, array: Vec, array_spa items_str.trim().into(), nested_indent, visitor.shape(), - true, + NewlineMode::IfContainsNewLineAndWidth, ) } diff --git a/tooling/nargo_fmt/src/rewrite/expr.rs b/tooling/nargo_fmt/src/rewrite/expr.rs new file mode 100644 index 0000000000..32d104f559 --- /dev/null +++ b/tooling/nargo_fmt/src/rewrite/expr.rs @@ -0,0 +1,155 @@ +use noirc_frontend::{token::Token, ArrayLiteral, Expression, ExpressionKind, Literal, UnaryOp}; + +use crate::visitor::{ + expr::{format_brackets, format_parens, NewlineMode}, + ExpressionType, FmtVisitor, Indent, Shape, +}; + +pub(crate) fn rewrite_sub_expr( + visitor: &FmtVisitor, + shape: Shape, + expression: Expression, +) -> String { + rewrite(visitor, expression, ExpressionType::SubExpression, shape) +} + +pub(crate) fn rewrite( + visitor: &FmtVisitor, + Expression { kind, span }: Expression, + expr_type: ExpressionType, + shape: Shape, +) -> String { + match kind { + ExpressionKind::Block(block) => { + let mut visitor = visitor.fork(); + visitor.visit_block(block, span); + visitor.finish() + } + ExpressionKind::Prefix(prefix) => { + let op = match prefix.operator { + UnaryOp::Minus => "-", + UnaryOp::Not => "!", + UnaryOp::MutableReference => "&mut ", + UnaryOp::Dereference { implicitly_added } => { + if implicitly_added { + "" + } else { + "*" + } + } + }; + + format!("{op}{}", rewrite_sub_expr(visitor, shape, prefix.rhs)) + } + ExpressionKind::Cast(cast) => { + format!("{} as {}", rewrite_sub_expr(visitor, shape, cast.lhs), cast.r#type) + } + kind @ ExpressionKind::Infix(_) => { + super::infix(visitor.fork(), Expression { kind, span }, shape) + } + ExpressionKind::Call(call_expr) => { + let args_span = + visitor.span_before(call_expr.func.span.end()..span.end(), Token::LeftParen); + + let callee = rewrite_sub_expr(visitor, shape, *call_expr.func); + let args = format_parens( + visitor.config.fn_call_width.into(), + visitor.fork(), + shape, + false, + call_expr.arguments, + args_span, + true, + NewlineMode::IfContainsNewLineAndWidth, + ); + + format!("{callee}{args}") + } + ExpressionKind::MethodCall(method_call_expr) => { + let args_span = visitor.span_before( + method_call_expr.method_name.span().end()..span.end(), + Token::LeftParen, + ); + + let object = rewrite_sub_expr(visitor, shape, method_call_expr.object); + let method = method_call_expr.method_name.to_string(); + let args = format_parens( + visitor.config.fn_call_width.into(), + visitor.fork(), + shape, + false, + method_call_expr.arguments, + args_span, + true, + NewlineMode::IfContainsNewLineAndWidth, + ); + + format!("{object}.{method}{args}") + } + ExpressionKind::MemberAccess(member_access_expr) => { + let lhs_str = rewrite_sub_expr(visitor, shape, member_access_expr.lhs); + format!("{}.{}", lhs_str, member_access_expr.rhs) + } + ExpressionKind::Index(index_expr) => { + let index_span = visitor + .span_before(index_expr.collection.span.end()..span.end(), Token::LeftBracket); + + let collection = rewrite_sub_expr(visitor, shape, index_expr.collection); + let index = format_brackets(visitor.fork(), false, vec![index_expr.index], index_span); + + format!("{collection}{index}") + } + ExpressionKind::Tuple(exprs) => format_parens( + None, + visitor.fork(), + shape, + exprs.len() == 1, + exprs, + span, + true, + NewlineMode::Normal, + ), + ExpressionKind::Literal(literal) => match literal { + Literal::Integer(_, _) + | Literal::Bool(_) + | Literal::Str(_) + | Literal::RawStr(..) + | Literal::FmtStr(_) => visitor.slice(span).to_string(), + Literal::Array(ArrayLiteral::Repeated { repeated_element, length }) => { + let repeated = rewrite_sub_expr(visitor, shape, *repeated_element); + let length = rewrite_sub_expr(visitor, shape, *length); + + format!("[{repeated}; {length}]") + } + Literal::Array(ArrayLiteral::Standard(exprs)) => { + super::array(visitor.fork(), exprs, span) + } + Literal::Unit => "()".to_string(), + }, + ExpressionKind::Parenthesized(sub_expr) => { + super::parenthesized(visitor, shape, span, *sub_expr) + } + ExpressionKind::Constructor(constructor) => { + let type_name = visitor.slice(span.start()..constructor.type_name.span().end()); + let fields_span = visitor + .span_before(constructor.type_name.span().end()..span.end(), Token::LeftBrace); + + visitor.format_struct_lit(type_name, fields_span, *constructor) + } + ExpressionKind::If(if_expr) => { + let allow_single_line = expr_type == ExpressionType::SubExpression; + + if allow_single_line { + let mut visitor = visitor.fork(); + visitor.indent = Indent::default(); + if let Some(line) = visitor.format_if_single_line(*if_expr.clone()) { + return line; + } + } + + visitor.format_if(*if_expr) + } + ExpressionKind::Lambda(_) | ExpressionKind::Variable(_) => visitor.slice(span).to_string(), + ExpressionKind::Error => unreachable!(), + } +} diff --git a/tooling/nargo_fmt/src/rewrite/infix.rs b/tooling/nargo_fmt/src/rewrite/infix.rs index 0fbfa07a84..15f5fe23aa 100644 --- a/tooling/nargo_fmt/src/rewrite/infix.rs +++ b/tooling/nargo_fmt/src/rewrite/infix.rs @@ -3,8 +3,9 @@ use std::iter::zip; use noirc_frontend::{Expression, ExpressionKind}; use crate::{ + rewrite, utils::{first_line_width, is_single_line}, - visitor::{ExpressionType, FmtVisitor, Shape}, + visitor::{FmtVisitor, Shape}, }; pub(crate) fn rewrite(visitor: FmtVisitor, expr: Expression, shape: Shape) -> String { @@ -16,9 +17,9 @@ pub(crate) fn rewrite(visitor: FmtVisitor, expr: Expression, shape: Shape) -> St format!( "{} {} {}", - visitor.format_sub_expr(infix.lhs), + rewrite::sub_expr(&visitor, shape, infix.lhs), infix.operator.contents.as_string(), - visitor.format_sub_expr(infix.rhs) + rewrite::sub_expr(&visitor, shape, infix.rhs) ) } } @@ -87,10 +88,10 @@ pub(crate) fn flatten( } _ => { let rewrite = if result.is_empty() { - visitor.format_expr(node.clone(), ExpressionType::SubExpression) + rewrite::sub_expr(&visitor, visitor.shape(), node.clone()) } else { visitor.indent.block_indent(visitor.config); - visitor.format_expr(node.clone(), ExpressionType::SubExpression) + rewrite::sub_expr(&visitor, visitor.shape(), node.clone()) }; result.push(rewrite); diff --git a/tooling/nargo_fmt/src/rewrite/parenthesized.rs b/tooling/nargo_fmt/src/rewrite/parenthesized.rs new file mode 100644 index 0000000000..3926b52cb7 --- /dev/null +++ b/tooling/nargo_fmt/src/rewrite/parenthesized.rs @@ -0,0 +1,67 @@ +use noirc_frontend::{hir::resolution::errors::Span, Expression, ExpressionKind}; + +use crate::visitor::{FmtVisitor, Shape}; + +pub(crate) fn rewrite( + visitor: &FmtVisitor<'_>, + shape: Shape, + mut span: Span, + mut sub_expr: Expression, +) -> String { + let remove_nested_parens = visitor.config.remove_nested_parens; + + let mut leading; + let mut trailing; + + loop { + let leading_span = span.start() + 1..sub_expr.span.start(); + let trailing_span = sub_expr.span.end()..span.end() - 1; + + leading = visitor.format_comment(leading_span.into()); + trailing = visitor.format_comment(trailing_span.into()); + + if let ExpressionKind::Parenthesized(ref sub_sub_expr) = sub_expr.kind { + if remove_nested_parens && leading.is_empty() && trailing.is_empty() { + span = sub_expr.span; + sub_expr = *sub_sub_expr.clone(); + continue; + } + } + + break; + } + + if !leading.contains("//") && !trailing.contains("//") { + let sub_expr = super::sub_expr(visitor, shape, sub_expr); + format!("({leading}{sub_expr}{trailing})") + } else { + let mut visitor = visitor.fork(); + + let indent = visitor.indent.to_string_with_newline(); + visitor.indent.block_indent(visitor.config); + let nested_indent = visitor.indent.to_string_with_newline(); + + let sub_expr = super::sub_expr(&visitor, shape, sub_expr); + + let mut result = String::new(); + result.push('('); + + if !leading.is_empty() { + result.push_str(&nested_indent); + result.push_str(&leading); + } + + result.push_str(&nested_indent); + result.push_str(&sub_expr); + + if !trailing.is_empty() { + result.push_str(&nested_indent); + result.push_str(&trailing); + } + + result.push_str(&indent); + result.push(')'); + + result + } +} diff --git a/tooling/nargo_fmt/src/rewrite/typ.rs b/tooling/nargo_fmt/src/rewrite/typ.rs new file mode 100644 index 0000000000..4c6411e92b --- /dev/null +++ b/tooling/nargo_fmt/src/rewrite/typ.rs @@ -0,0 +1,70 @@ +use noirc_frontend::{UnresolvedType, UnresolvedTypeData}; + +use crate::{ + utils::span_is_empty, + visitor::{FmtVisitor, Shape}, +}; + +pub(crate) fn rewrite(visitor: &FmtVisitor, _shape: Shape, typ: UnresolvedType) -> String { + match typ.typ { + UnresolvedTypeData::Array(length, element) => { + let typ = rewrite(visitor, _shape, *element); + if let Some(length) = length { + let length = visitor.slice(length.span()); + format!("[{typ}; {length}]") + } else { + format!("[{typ}]") + } + } + UnresolvedTypeData::Parenthesized(typ) => { + let typ = rewrite(visitor, _shape, *typ); + format!("({typ})") + } + UnresolvedTypeData::MutableReference(typ) => { + let typ = rewrite(visitor, _shape, *typ); + format!("&mut {typ}") + } + UnresolvedTypeData::Tuple(mut types) => { + if types.len() == 1 { + let typ = types.pop().unwrap(); + let typ = rewrite(visitor, _shape, typ); + + format!("({typ},)") + } else { + let types: Vec<_> = + types.into_iter().map(|typ| rewrite(visitor, _shape, typ)).collect(); + let types = types.join(", "); + format!("({types})") + } + } + UnresolvedTypeData::Function(args, return_type, env) => { + let env = if span_is_empty(env.span.unwrap()) { + "".into() + } else { + let ty = rewrite(visitor, _shape, *env); + format!("[{ty}]") + }; + + let args = args + .into_iter() + .map(|arg| rewrite(visitor, _shape, arg)) + .collect::>() + .join(", "); + + let return_type = rewrite(visitor, _shape, *return_type); + + format!("fn{env}({args}) -> {return_type}") + } + UnresolvedTypeData::Unspecified => todo!(), + UnresolvedTypeData::FieldElement + | UnresolvedTypeData::Integer(_, _) + | UnresolvedTypeData::Bool + | UnresolvedTypeData::Named(_, _) + | UnresolvedTypeData::Unit + | UnresolvedTypeData::Expression(_) + | UnresolvedTypeData::String(_) + | UnresolvedTypeData::FormatString(_, _) + | UnresolvedTypeData::TraitAsType(_, _) => visitor.slice(typ.span.unwrap()).into(), + UnresolvedTypeData::Error => unreachable!(), + } +} diff --git a/tooling/nargo_fmt/src/utils.rs b/tooling/nargo_fmt/src/utils.rs index 13938079e6..1160f01972 100644 --- a/tooling/nargo_fmt/src/utils.rs +++ b/tooling/nargo_fmt/src/utils.rs @@ -1,4 +1,5 @@ -use crate::visitor::FmtVisitor; +use crate::rewrite; +use crate::visitor::{FmtVisitor, Shape}; use noirc_frontend::hir::resolution::errors::Span; use noirc_frontend::lexer::Lexer; use noirc_frontend::token::Token; @@ -40,15 +41,22 @@ impl Expr { pub(crate) struct Exprs<'me, T> { pub(crate) visitor: &'me FmtVisitor<'me>, + shape: Shape, pub(crate) elements: std::iter::Peekable>, pub(crate) last_position: u32, pub(crate) end_position: u32, } impl<'me, T: Item> Exprs<'me, T> { - pub(crate) fn new(visitor: &'me FmtVisitor<'me>, span: Span, elements: Vec) -> Self { + pub(crate) fn new( + visitor: &'me FmtVisitor<'me>, + shape: Shape, + span: Span, + elements: Vec, + ) -> Self { Self { visitor, + shape, last_position: span.start() + 1, /*(*/ end_position: span.end() - 1, /*)*/ elements: elements.into_iter().peekable(), @@ -70,7 +78,7 @@ impl Iterator for Exprs<'_, T> { let next_start = self.elements.peek().map_or(self.end_position, |expr| expr.start()); let (leading, different_line) = self.leading(start, end); - let expr = element.format(self.visitor); + let expr = element.format(self.visitor, self.shape); let trailing = self.trailing(element_span.end(), next_start, is_last); Expr { leading, value: expr, trailing, different_line }.into() @@ -112,7 +120,7 @@ impl<'me, T> Exprs<'me, T> { pub(crate) trait FindToken { fn find_token(&self, token: Token) -> Option; - fn find_token_with(&self, f: impl Fn(&Token) -> bool) -> Option; + fn find_token_with(&self, f: impl Fn(&Token) -> bool) -> Option; } impl FindToken for str { @@ -120,11 +128,11 @@ impl FindToken for str { Lexer::new(self).flatten().find_map(|it| (it.token() == &token).then(|| it.to_span())) } - fn find_token_with(&self, f: impl Fn(&Token) -> bool) -> Option { + fn find_token_with(&self, f: impl Fn(&Token) -> bool) -> Option { Lexer::new(self) .skip_comments(false) .flatten() - .find_map(|spanned| f(spanned.token()).then(|| spanned.to_span().end())) + .find_map(|spanned| f(spanned.token()).then(|| spanned.to_span())) } } @@ -134,7 +142,7 @@ pub(crate) fn find_comment_end(slice: &str, is_last: bool) -> usize { .find_token_with(|token| { matches!(token, Token::LineComment(_, _) | Token::BlockComment(_, _)) }) - .map(|index| index as usize) + .map(|index| index.end() as usize) .unwrap_or(slice.len()) } @@ -196,7 +204,7 @@ pub(crate) fn count_newlines(slice: &str) -> usize { pub(crate) trait Item { fn span(&self) -> Span; - fn format(self, visitor: &FmtVisitor) -> String; + fn format(self, visitor: &FmtVisitor, shape: Shape) -> String; fn start(&self) -> u32 { self.span().start() @@ -212,8 +220,8 @@ impl Item for Expression { self.span } - fn format(self, visitor: &FmtVisitor) -> String { - visitor.format_sub_expr(self) + fn format(self, visitor: &FmtVisitor, shape: Shape) -> String { + rewrite::sub_expr(visitor, shape, self) } } @@ -223,11 +231,11 @@ impl Item for (Ident, Expression) { (name.span().start()..value.span.end()).into() } - fn format(self, visitor: &FmtVisitor) -> String { + fn format(self, visitor: &FmtVisitor, shape: Shape) -> String { let (name, expr) = self; let name = name.0.contents; - let expr = visitor.format_sub_expr(expr); + let expr = rewrite::sub_expr(visitor, shape, expr); if name == expr { name @@ -242,13 +250,14 @@ impl Item for Param { self.span } - fn format(self, visitor: &FmtVisitor) -> String { + fn format(self, visitor: &FmtVisitor, shape: Shape) -> String { let visibility = match self.visibility { Visibility::Public => "pub ", Visibility::Private => "", + Visibility::DataBus => "call_data", }; let pattern = visitor.slice(self.pattern.span()); - let ty = visitor.slice(self.typ.span.unwrap()); + let ty = rewrite::typ(visitor, shape, self.typ); format!("{pattern}: {visibility}{ty}") } @@ -259,7 +268,7 @@ impl Item for Ident { self.span() } - fn format(self, visitor: &FmtVisitor) -> String { + fn format(self, visitor: &FmtVisitor, _shape: Shape) -> String { visitor.slice(self.span()).into() } } @@ -268,6 +277,10 @@ pub(crate) fn first_line_width(exprs: &str) -> usize { exprs.lines().next().map_or(0, |line: &str| line.chars().count()) } +pub(crate) fn last_line_width(s: &str) -> usize { + s.rsplit('\n').next().unwrap_or("").chars().count() +} + pub(crate) fn is_single_line(s: &str) -> bool { !s.chars().any(|c| c == '\n') } @@ -275,3 +288,15 @@ pub(crate) fn is_single_line(s: &str) -> bool { pub(crate) fn last_line_contains_single_line_comment(s: &str) -> bool { s.lines().last().map_or(false, |line| line.contains("//")) } + +pub(crate) fn last_line_used_width(s: &str, offset: usize) -> usize { + if s.contains('\n') { + last_line_width(s) + } else { + offset + s.chars().count() + } +} + +pub(crate) fn span_is_empty(span: Span) -> bool { + span.start() == span.end() +} diff --git a/tooling/nargo_fmt/src/visitor.rs b/tooling/nargo_fmt/src/visitor.rs index cf3b3a41e8..85989db79d 100644 --- a/tooling/nargo_fmt/src/visitor.rs +++ b/tooling/nargo_fmt/src/visitor.rs @@ -30,12 +30,16 @@ impl<'me> FmtVisitor<'me> { } } + pub(crate) fn budget(&self, used_width: usize) -> usize { + self.config.max_width.saturating_sub(used_width) + } + pub(crate) fn slice(&self, span: impl Into) -> &'me str { let span = span.into(); &self.source[span.start() as usize..span.end() as usize] } - fn span_after(&self, span: impl Into, token: Token) -> Span { + pub(crate) fn span_after(&self, span: impl Into, token: Token) -> Span { let span = span.into(); let slice = self.slice(span); @@ -44,7 +48,7 @@ impl<'me> FmtVisitor<'me> { (span.start() + offset..span.end()).into() } - fn span_before(&self, span: impl Into, token: Token) -> Span { + pub(crate) fn span_before(&self, span: impl Into, token: Token) -> Span { let span = span.into(); let slice = self.slice(span); @@ -253,10 +257,12 @@ impl Indent { self.block_indent } + #[track_caller] pub(crate) fn block_indent(&mut self, config: &Config) { self.block_indent += config.tab_spaces; } + #[track_caller] pub(crate) fn block_unindent(&mut self, config: &Config) { self.block_indent -= config.tab_spaces; } diff --git a/tooling/nargo_fmt/src/visitor/expr.rs b/tooling/nargo_fmt/src/visitor/expr.rs index 8492fd5c05..586d9583e3 100644 --- a/tooling/nargo_fmt/src/visitor/expr.rs +++ b/tooling/nargo_fmt/src/visitor/expr.rs @@ -1,10 +1,9 @@ use noirc_frontend::{ - hir::resolution::errors::Span, lexer::Lexer, token::Token, ArrayLiteral, BlockExpression, - ConstructorExpression, Expression, ExpressionKind, IfExpression, Literal, Statement, - StatementKind, UnaryOp, + hir::resolution::errors::Span, lexer::Lexer, token::Token, BlockExpression, + ConstructorExpression, Expression, ExpressionKind, IfExpression, Statement, StatementKind, }; -use super::{ExpressionType, FmtVisitor, Indent, Shape}; +use super::{ExpressionType, FmtVisitor, Shape}; use crate::{ rewrite, utils::{self, first_line_width, Expr, FindToken, Item}, @@ -14,199 +13,14 @@ use crate::{ impl FmtVisitor<'_> { pub(crate) fn visit_expr(&mut self, expr: Expression, expr_type: ExpressionType) { let span = expr.span; - let rewrite = self.format_expr(expr, expr_type); + let rewrite = rewrite::expr(self, expr, expr_type, self.shape()); self.push_rewrite(rewrite, span); self.last_position = span.end(); } - pub(crate) fn format_sub_expr(&self, expression: Expression) -> String { - self.format_expr(expression, ExpressionType::SubExpression) - } - - pub(crate) fn format_expr( - &self, - Expression { kind, mut span }: Expression, - expr_type: ExpressionType, - ) -> String { - match kind { - ExpressionKind::Block(block) => { - let mut visitor = self.fork(); - visitor.visit_block(block, span); - visitor.buffer - } - ExpressionKind::Prefix(prefix) => { - let op = match prefix.operator { - UnaryOp::Minus => "-", - UnaryOp::Not => "!", - UnaryOp::MutableReference => "&mut ", - UnaryOp::Dereference { implicitly_added } => { - if implicitly_added { - "" - } else { - "*" - } - } - }; - - format!("{op}{}", self.format_sub_expr(prefix.rhs)) - } - ExpressionKind::Cast(cast) => { - format!("{} as {}", self.format_sub_expr(cast.lhs), cast.r#type) - } - kind @ ExpressionKind::Infix(_) => { - let shape = self.shape(); - rewrite::infix(self.fork(), Expression { kind, span }, shape) - } - ExpressionKind::Call(call_expr) => { - let args_span = - self.span_before(call_expr.func.span.end()..span.end(), Token::LeftParen); - - let callee = self.format_sub_expr(*call_expr.func); - let args = format_parens( - self.config.fn_call_width.into(), - self.fork(), - false, - call_expr.arguments, - args_span, - ); - - format!("{callee}{args}") - } - ExpressionKind::MethodCall(method_call_expr) => { - let args_span = self.span_before( - method_call_expr.method_name.span().end()..span.end(), - Token::LeftParen, - ); - - let object = self.format_sub_expr(method_call_expr.object); - let method = method_call_expr.method_name.to_string(); - let args = format_parens( - self.config.fn_call_width.into(), - self.fork(), - false, - method_call_expr.arguments, - args_span, - ); - - format!("{object}.{method}{args}") - } - ExpressionKind::MemberAccess(member_access_expr) => { - let lhs_str = self.format_sub_expr(member_access_expr.lhs); - format!("{}.{}", lhs_str, member_access_expr.rhs) - } - ExpressionKind::Index(index_expr) => { - let index_span = self - .span_before(index_expr.collection.span.end()..span.end(), Token::LeftBracket); - - let collection = self.format_sub_expr(index_expr.collection); - let index = format_brackets(self.fork(), false, vec![index_expr.index], index_span); - - format!("{collection}{index}") - } - ExpressionKind::Tuple(exprs) => { - format_parens(None, self.fork(), exprs.len() == 1, exprs, span) - } - ExpressionKind::Literal(literal) => match literal { - Literal::Integer(_) | Literal::Bool(_) | Literal::Str(_) | Literal::FmtStr(_) => { - self.slice(span).to_string() - } - Literal::Array(ArrayLiteral::Repeated { repeated_element, length }) => { - let repeated = self.format_sub_expr(*repeated_element); - let length = self.format_sub_expr(*length); - - format!("[{repeated}; {length}]") - } - Literal::Array(ArrayLiteral::Standard(exprs)) => { - rewrite::array(self.fork(), exprs, span) - } - Literal::Unit => "()".to_string(), - }, - ExpressionKind::Parenthesized(mut sub_expr) => { - let remove_nested_parens = self.config.remove_nested_parens; - - let mut leading; - let mut trailing; - - loop { - let leading_span = span.start() + 1..sub_expr.span.start(); - let trailing_span = sub_expr.span.end()..span.end() - 1; - - leading = self.format_comment(leading_span.into()); - trailing = self.format_comment(trailing_span.into()); - - if let ExpressionKind::Parenthesized(ref sub_sub_expr) = sub_expr.kind { - if remove_nested_parens && leading.is_empty() && trailing.is_empty() { - span = sub_expr.span; - sub_expr = sub_sub_expr.clone(); - continue; - } - } - - break; - } - - if !leading.contains("//") && !trailing.contains("//") { - let sub_expr = self.format_sub_expr(*sub_expr); - format!("({leading}{sub_expr}{trailing})") - } else { - let mut visitor = self.fork(); - - let indent = visitor.indent.to_string_with_newline(); - visitor.indent.block_indent(self.config); - let nested_indent = visitor.indent.to_string_with_newline(); - - let sub_expr = visitor.format_sub_expr(*sub_expr); - - let mut result = String::new(); - result.push('('); - - if !leading.is_empty() { - result.push_str(&nested_indent); - result.push_str(&leading); - } - - result.push_str(&nested_indent); - result.push_str(&sub_expr); - - if !trailing.is_empty() { - result.push_str(&nested_indent); - result.push_str(&trailing); - } - - result.push_str(&indent); - result.push(')'); - - result - } - } - ExpressionKind::Constructor(constructor) => { - let type_name = self.slice(span.start()..constructor.type_name.span().end()); - let fields_span = self - .span_before(constructor.type_name.span().end()..span.end(), Token::LeftBrace); - - self.format_struct_lit(type_name, fields_span, *constructor) - } - ExpressionKind::If(if_expr) => { - let allow_single_line = expr_type == ExpressionType::SubExpression; - - if allow_single_line { - let mut visitor = self.fork(); - visitor.indent = Indent::default(); - if let Some(line) = visitor.format_if_single_line(*if_expr.clone()) { - return line; - } - } - - self.format_if(*if_expr) - } - ExpressionKind::Lambda(_) | ExpressionKind::Variable(_) => self.slice(span).to_string(), - ExpressionKind::Error => unreachable!(), - } - } - - fn format_if(&self, if_expr: IfExpression) -> String { - let condition_str = self.format_sub_expr(if_expr.condition); - let consequence_str = self.format_sub_expr(if_expr.consequence); + pub(crate) fn format_if(&self, if_expr: IfExpression) -> String { + let condition_str = rewrite::sub_expr(self, self.shape(), if_expr.condition); + let consequence_str = rewrite::sub_expr(self, self.shape(), if_expr.consequence); let mut result = format!("if {condition_str} {consequence_str}"); @@ -216,7 +30,7 @@ impl FmtVisitor<'_> { { self.format_if(*if_expr) } else { - self.format_expr(alternative, ExpressionType::Statement) + rewrite::expr(self, alternative, ExpressionType::Statement, self.shape()) }; result.push_str(" else "); @@ -226,9 +40,10 @@ impl FmtVisitor<'_> { result } - fn format_if_single_line(&self, if_expr: IfExpression) -> Option { - let condition_str = self.format_sub_expr(if_expr.condition); - let consequence_str = self.format_sub_expr(extract_simple_expr(if_expr.consequence)?); + pub(crate) fn format_if_single_line(&self, if_expr: IfExpression) -> Option { + let condition_str = rewrite::sub_expr(self, self.shape(), if_expr.condition); + let consequence_str = + rewrite::sub_expr(self, self.shape(), extract_simple_expr(if_expr.consequence)?); let if_str = if let Some(alternative) = if_expr.alternative { let alternative_str = if let Some(ExpressionKind::If(_)) = @@ -236,7 +51,12 @@ impl FmtVisitor<'_> { { return None; } else { - self.format_expr(extract_simple_expr(alternative)?, ExpressionType::Statement) + rewrite::expr( + self, + extract_simple_expr(alternative)?, + ExpressionType::Statement, + self.shape(), + ) }; format!("if {} {{ {} }} else {{ {} }}", condition_str, consequence_str, alternative_str) @@ -247,7 +67,7 @@ impl FmtVisitor<'_> { (if_str.len() <= self.config.single_line_if_else_max_width).then_some(if_str) } - fn format_struct_lit( + pub(crate) fn format_struct_lit( &self, type_name: &str, fields_span: Span, @@ -261,13 +81,15 @@ impl FmtVisitor<'_> { let nested_indent = visitor.shape(); let exprs: Vec<_> = - utils::Exprs::new(&visitor, fields_span, constructor.fields).collect(); + utils::Exprs::new(&visitor, nested_indent, fields_span, constructor.fields) + .collect(); let exprs = format_exprs( visitor.config, Tactic::HorizontalVertical, false, exprs, nested_indent, + true, ); visitor.indent.block_unindent(visitor.config); @@ -365,29 +187,32 @@ impl FmtVisitor<'_> { } } +// TODO: fixme #[allow(clippy::too_many_arguments)] pub(crate) fn format_seq( + shape: Shape, prefix: &str, suffix: &str, - mut visitor: FmtVisitor, + visitor: FmtVisitor, trailing_comma: bool, exprs: Vec, span: Span, tactic: Tactic, - soft_newline: bool, + mode: NewlineMode, + reduce: bool, ) -> String { - visitor.indent.block_indent(visitor.config); + let mut nested_indent = shape; + let shape = shape; - let nested_indent = visitor.shape(); - let exprs: Vec<_> = utils::Exprs::new(&visitor, span, exprs).collect(); - let exprs = format_exprs(visitor.config, tactic, trailing_comma, exprs, nested_indent); + nested_indent.indent.block_indent(visitor.config); - visitor.indent.block_unindent(visitor.config); + let exprs: Vec<_> = utils::Exprs::new(&visitor, nested_indent, span, exprs).collect(); + let exprs = format_exprs(visitor.config, tactic, trailing_comma, exprs, nested_indent, reduce); - wrap_exprs(prefix, suffix, exprs, nested_indent, visitor.shape(), soft_newline) + wrap_exprs(prefix, suffix, exprs, nested_indent, shape, mode) } -fn format_brackets( +pub(crate) fn format_brackets( visitor: FmtVisitor, trailing_comma: bool, exprs: Vec, @@ -395,6 +220,7 @@ fn format_brackets( ) -> String { let array_width = visitor.config.array_width; format_seq( + visitor.shape(), "[", "]", visitor, @@ -402,19 +228,25 @@ fn format_brackets( exprs, span, Tactic::LimitedHorizontalVertical(array_width), + NewlineMode::Normal, false, ) } -fn format_parens( +// TODO: fixme +#[allow(clippy::too_many_arguments)] +pub(crate) fn format_parens( max_width: Option, visitor: FmtVisitor, + shape: Shape, trailing_comma: bool, exprs: Vec, span: Span, + reduce: bool, + mode: NewlineMode, ) -> String { let tactic = max_width.map(Tactic::LimitedHorizontalVertical).unwrap_or(Tactic::Horizontal); - format_seq("(", ")", visitor, trailing_comma, exprs, span, tactic, false) + format_seq(shape, "(", ")", visitor, trailing_comma, exprs, span, tactic, mode, reduce) } fn format_exprs( @@ -423,11 +255,12 @@ fn format_exprs( trailing_comma: bool, exprs: Vec, shape: Shape, + reduce: bool, ) -> String { let mut result = String::new(); let indent_str = shape.indent.to_string(); - let tactic = tactic.definitive(&exprs, config.short_array_element_width_threshold); + let tactic = tactic.definitive(&exprs, config.short_array_element_width_threshold, reduce); let mut exprs = exprs.into_iter().enumerate().peekable(); let mut line_len = 0; let mut prev_expr_trailing_comment = false; @@ -500,18 +333,34 @@ fn format_exprs( result } +#[derive(PartialEq, Eq)] +pub(crate) enum NewlineMode { + IfContainsNewLine, + IfContainsNewLineAndWidth, + Normal, +} + pub(crate) fn wrap_exprs( prefix: &str, suffix: &str, exprs: String, nested_shape: Shape, shape: Shape, - soft_newline: bool, + newline_mode: NewlineMode, ) -> String { - let first_line_width = first_line_width(&exprs); - - let force_one_line = - if soft_newline { !exprs.contains('\n') } else { first_line_width <= shape.width }; + let mut force_one_line = if newline_mode == NewlineMode::IfContainsNewLine { + true + } else { + first_line_width(&exprs) <= shape.width + }; + + if matches!( + newline_mode, + NewlineMode::IfContainsNewLine | NewlineMode::IfContainsNewLineAndWidth + ) && force_one_line + { + force_one_line = !exprs.contains('\n'); + } if force_one_line { let allow_trailing_newline = exprs @@ -548,7 +397,8 @@ impl Tactic { fn definitive( self, exprs: &[Expr], - short_array_element_width_threshold: usize, + short_width_threshold: usize, + reduce: bool, ) -> DefinitiveTactic { let tactic = || { let has_single_line_comment = exprs.iter().any(|item| { @@ -582,7 +432,12 @@ impl Tactic { } }; - tactic().reduce(exprs, short_array_element_width_threshold) + let definitive_tactic = tactic(); + if reduce { + definitive_tactic.reduce(exprs, short_width_threshold) + } else { + definitive_tactic + } } } diff --git a/tooling/nargo_fmt/src/visitor/item.rs b/tooling/nargo_fmt/src/visitor/item.rs index 7774618afe..eb2086168b 100644 --- a/tooling/nargo_fmt/src/visitor/item.rs +++ b/tooling/nargo_fmt/src/visitor/item.rs @@ -1,17 +1,23 @@ use noirc_frontend::{ + hir::resolution::errors::Span, parser::{Item, ItemKind}, - token::Token, + token::{Keyword, Token}, Distinctness, NoirFunction, ParsedModule, Visibility, }; -use crate::{utils::last_line_contains_single_line_comment, visitor::expr::format_seq}; +use crate::{ + rewrite, + utils::{last_line_contains_single_line_comment, last_line_used_width, FindToken}, + visitor::expr::{format_seq, NewlineMode}, +}; -use super::expr::Tactic::LimitedHorizontalVertical; +use super::{ + expr::Tactic::{HorizontalVertical, LimitedHorizontalVertical}, + Shape, +}; impl super::FmtVisitor<'_> { fn format_fn_before_block(&self, func: NoirFunction, start: u32) -> (String, bool) { - let tactic = LimitedHorizontalVertical(self.config.max_width); - let name_span = func.name_ident().span(); let func_span = func.span(); @@ -30,6 +36,7 @@ impl super::FmtVisitor<'_> { let params_span = params_open..params_end; let return_type_span = func.return_type().span; + let return_type = self.format_return_type(return_type_span, &func, func_span, params_end); let parameters = func.def.parameters; if !func.def.generics.is_empty() { @@ -39,7 +46,18 @@ impl super::FmtVisitor<'_> { let generics = func.def.generics; let span = (start..end).into(); - let generics = format_seq("<", ">", self.fork(), false, generics, span, tactic, false); + let generics = format_seq( + self.shape(), + "<", + ">", + self.fork(), + false, + generics, + span, + HorizontalVertical, + NewlineMode::IfContainsNewLine, + false, + ); result.push_str(&generics); } @@ -47,10 +65,52 @@ impl super::FmtVisitor<'_> { let parameters = if parameters.is_empty() { self.slice(params_span).into() } else { - format_seq("(", ")", self.fork(), false, parameters, params_span.into(), tactic, true) + let fn_start = result + .find_token_with(|token| { + matches!(token, Token::Keyword(Keyword::Fn | Keyword::Unconstrained)) + }) + .unwrap() + .start(); + + let slice = self.slice(fn_start..result.len() as u32); + let indent = self.indent; + let used_width = last_line_used_width(slice, indent.width()); + let overhead = if return_type.is_empty() { 2 } else { 3 }; // 2 = `()`, 3 = `() ` + let one_line_budget = self.budget(used_width + return_type.len() + overhead); + let shape = Shape { width: one_line_budget, indent }; + + let tactic = LimitedHorizontalVertical(one_line_budget); + + format_seq( + shape, + "(", + ")", + self.fork(), + false, + parameters, + params_span.into(), + tactic, + NewlineMode::IfContainsNewLine, + false, + ) }; result.push_str(¶meters); + result.push_str(&return_type); + + let maybe_comment = self.slice(params_end..func_span.start()); + + (result.trim_end().to_string(), last_line_contains_single_line_comment(maybe_comment)) + } + + fn format_return_type( + &self, + return_type_span: Option, + func: &NoirFunction, + func_span: Span, + params_end: u32, + ) -> String { + let mut result = String::new(); if let Some(span) = return_type_span { result.push_str(" -> "); @@ -63,7 +123,8 @@ impl super::FmtVisitor<'_> { result.push_str("pub "); } - result.push_str(self.slice(span)); + let typ = rewrite::typ(self, self.shape(), func.return_type()); + result.push_str(&typ); let slice = self.slice(span.end()..func_span.start()); if !slice.trim().is_empty() { @@ -73,9 +134,7 @@ impl super::FmtVisitor<'_> { result.push_str(self.slice(params_end..func_span.start())); } - let maybe_comment = self.slice(params_end..func_span.start()); - - (result.trim_end().to_string(), last_line_contains_single_line_comment(maybe_comment)) + result } pub(crate) fn visit_file(&mut self, module: ParsedModule) { diff --git a/tooling/nargo_fmt/src/visitor/stmt.rs b/tooling/nargo_fmt/src/visitor/stmt.rs index b6dd67323f..800a8656ef 100644 --- a/tooling/nargo_fmt/src/visitor/stmt.rs +++ b/tooling/nargo_fmt/src/visitor/stmt.rs @@ -4,7 +4,9 @@ use noirc_frontend::{ ConstrainKind, ConstrainStatement, ExpressionKind, ForRange, Statement, StatementKind, }; -use super::ExpressionType; +use crate::{rewrite, visitor::expr::wrap_exprs}; + +use super::{expr::NewlineMode, ExpressionType}; impl super::FmtVisitor<'_> { pub(crate) fn visit_stmts(&mut self, stmts: Vec) { @@ -25,36 +27,57 @@ impl super::FmtVisitor<'_> { StatementKind::Let(let_stmt) => { let let_str = self.slice(span.start()..let_stmt.expression.span.start()).trim_end(); - let expr_str = - self.format_expr(let_stmt.expression, ExpressionType::SubExpression); + + let expr_str = rewrite::sub_expr(self, self.shape(), let_stmt.expression); self.push_rewrite(format!("{let_str} {expr_str};"), span); } StatementKind::Constrain(ConstrainStatement(expr, message, kind)) => { + let mut nested_shape = self.shape(); + let shape = nested_shape; + + nested_shape.indent.block_indent(self.config); + let message = message.map_or(String::new(), |message| format!(", \"{message}\"")); - let constrain = match kind { + + let (callee, args) = match kind { ConstrainKind::Assert => { - let assertion = self.format_sub_expr(expr); + let assertion = rewrite::sub_expr(self, nested_shape, expr); + let args = format!("{assertion}{message}"); - format!("assert({assertion}{message});") + ("assert", args) } ConstrainKind::AssertEq => { if let ExpressionKind::Infix(infix) = expr.kind { - let lhs = self.format_sub_expr(infix.lhs); - let rhs = self.format_sub_expr(infix.rhs); + let lhs = rewrite::sub_expr(self, nested_shape, infix.lhs); + let rhs = rewrite::sub_expr(self, nested_shape, infix.rhs); + + let args = format!("{lhs}, {rhs}{message}"); - format!("assert_eq({lhs}, {rhs}{message});") + ("assert_eq", args) } else { unreachable!() } } ConstrainKind::Constrain => { - let expr = self.format_sub_expr(expr); - format!("constrain {expr};") + let expr = rewrite::sub_expr(self, self.shape(), expr); + let constrain = format!("constrain {expr};"); + self.push_rewrite(constrain, span); + return; } }; + let args = wrap_exprs( + "(", + ")", + args, + nested_shape, + shape, + NewlineMode::IfContainsNewLineAndWidth, + ); + let constrain = format!("{callee}{args};"); + self.push_rewrite(constrain, span); } StatementKind::For(for_stmt) => { @@ -62,12 +85,12 @@ impl super::FmtVisitor<'_> { let range = match for_stmt.range { ForRange::Range(start, end) => format!( "{}..{}", - self.format_sub_expr(start), - self.format_sub_expr(end) + rewrite::sub_expr(self, self.shape(), start), + rewrite::sub_expr(self, self.shape(), end) ), - ForRange::Array(array) => self.format_sub_expr(array), + ForRange::Array(array) => rewrite::sub_expr(self, self.shape(), array), }; - let block = self.format_sub_expr(for_stmt.block); + let block = rewrite::sub_expr(self, self.shape(), for_stmt.block); let result = format!("for {identifier} in {range} {block}"); self.push_rewrite(result, span); diff --git a/tooling/nargo_fmt/tests/expected/call.nr b/tooling/nargo_fmt/tests/expected/call.nr index 3c9b36e840..de78d7c4ed 100644 --- a/tooling/nargo_fmt/tests/expected/call.nr +++ b/tooling/nargo_fmt/tests/expected/call.nr @@ -1,25 +1,33 @@ fn foo() { my_function(10, some_value, another_func(20, 30)); - outer_function(some_function(), // Original inner function call + outer_function( + some_function(), // Original inner function call another_function() // Original inner function call ); - outer_function(some_function(), // Original inner function call + outer_function( + some_function(), // Original inner function call another_function() // Original inner function call ); - my_function(// Comment + my_function( + // Comment some_value, /* Multiline Comment */ - another_func(20, 30)); + another_func(20, 30) + ); - my_function(some_function(10, "arg1", another_function()), - another_func(20, some_function(), 30)); + my_function( + some_function(10, "arg1", another_function()), + another_func(20, some_function(), 30) + ); - outer_function(some_function(), - another_function(some_function(), some_value)); + outer_function( + some_function(), + another_function(some_function(), some_value) + ); assert_eq(x, y); @@ -31,6 +39,12 @@ fn foo() { assert(x == y); - assert(p4_affine.eq(Gaffine::new(6890855772600357754907169075114257697580319025794532037257385534741338397365, - 4338620300185947561074059802482547481416142213883829469920100239455078257889))); + assert( + p4_affine.eq( + Gaffine::new( + 6890855772600357754907169075114257697580319025794532037257385534741338397365, + 4338620300185947561074059802482547481416142213883829469920100239455078257889 + ) + ) + ); } diff --git a/tooling/nargo_fmt/tests/expected/contract.nr b/tooling/nargo_fmt/tests/expected/contract.nr index 0d9bd2f100..d288b1af7e 100644 --- a/tooling/nargo_fmt/tests/expected/contract.nr +++ b/tooling/nargo_fmt/tests/expected/contract.nr @@ -57,9 +57,11 @@ contract Benchmarking { fn increment_balance(owner: Field, value: Field) { let current = storage.balances.at(owner).read(); storage.balances.at(owner).write(current + value); - let _callStackItem1 = context.call_public_function(context.this_address(), + let _callStackItem1 = context.call_public_function( + context.this_address(), compute_selector("broadcast(Field)"), - [owner]); + [owner] + ); } // Est ultricies integer quis auctor elit sed. In nibh mauris cursus mattis molestie a iaculis. @@ -68,7 +70,12 @@ contract Benchmarking { emit_unencrypted_log(&mut context, storage.balances.at(owner).read()); } - unconstrained fn compute_note_hash_and_nullifier(contract_address: Field, nonce: Field, storage_slot: Field, preimage: [Field; VALUE_NOTE_LEN]) -> [Field; 4] { + unconstrained fn compute_note_hash_and_nullifier( + contract_address: Field, + nonce: Field, + storage_slot: Field, + preimage: [Field; VALUE_NOTE_LEN] + ) -> [Field; 4] { let note_header = NoteHeader::new(contract_address, nonce, storage_slot); note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, preimage) } diff --git a/tooling/nargo_fmt/tests/expected/fn.nr b/tooling/nargo_fmt/tests/expected/fn.nr index 5bca2dd8bb..0088dba6a8 100644 --- a/tooling/nargo_fmt/tests/expected/fn.nr +++ b/tooling/nargo_fmt/tests/expected/fn.nr @@ -28,6 +28,36 @@ fn main( initial_call_stack_pointer: u64 ) -> pub ExecutionResult {} -fn apply_binary_field_op(lhs: RegisterIndex, rhs: RegisterIndex, result: RegisterIndex, op: u8, registers: &mut Registers) -> bool {} +fn apply_binary_field_op( + lhs: RegisterIndex, + rhs: RegisterIndex, + result: RegisterIndex, + op: u8, + registers: &mut Registers +) -> bool {} -fn main() -> distinct pub [Field;2] {} +fn main() -> distinct pub [Field; 2] {} + +fn ret_normal_lambda1() -> ((fn() -> Field)) {} + +fn ret_normal_lambda1() -> fn() -> Field {} + +fn ret_closure1() -> fn[(Field,)]() -> Field {} + +fn ret_closure2() -> fn[(Field, Field)]() -> Field {} + +fn ret_closure3() -> fn[(u32, u64)]() -> u64 {} + +fn make_counter() -> fn[(&mut Field,)]() -> Field {} + +fn get_some(generator: fn[Env]() -> Field) -> [Field; 5] {} + +fn main( + message: [u8; 10], + message_field: Field, + pub_key_x: Field, + pub_key_y: Field, + signature: [u8; 64] +) {} + +pub fn from_baz(x: [Field; crate::foo::MAGIC_NUMBER]) {} diff --git a/tooling/nargo_fmt/tests/expected/infix.nr b/tooling/nargo_fmt/tests/expected/infix.nr index cbc73045fe..228dfdf68c 100644 --- a/tooling/nargo_fmt/tests/expected/infix.nr +++ b/tooling/nargo_fmt/tests/expected/infix.nr @@ -9,10 +9,12 @@ fn foo() { } fn big() { - assert(bjj_affine.contains(bjj_affine.gen) + assert( + bjj_affine.contains(bjj_affine.gen) & bjj_affine.contains(p1_affine) & bjj_affine.contains(p2_affine) & bjj_affine.contains(p3_affine) & bjj_affine.contains(p4_affine) - & bjj_affine.contains(p5_affine)); + & bjj_affine.contains(p5_affine) + ); } diff --git a/tooling/nargo_fmt/tests/expected/let.nr b/tooling/nargo_fmt/tests/expected/let.nr index b60ae64479..c57801155a 100644 --- a/tooling/nargo_fmt/tests/expected/let.nr +++ b/tooling/nargo_fmt/tests/expected/let.nr @@ -1,7 +1,9 @@ //@error_on_lost_comment=false fn let_() { - let fn_call = my_function(some_function(10, "arg1", another_function()), - another_func(20, some_function(), 30)); + let fn_call = my_function( + some_function(10, "arg1", another_function()), + another_func(20, some_function(), 30) + ); let array = [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]], [[13, 14, 15], [16, 17, 18]]]; let padded_sha256_hash: [u8; 259] = [ @@ -15,7 +17,11 @@ fn let_() { 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]; - let a = BigUint56 { limbs: [1, 2, 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, 0, 0, 0] }; + let a = BigUint56 { + limbs: [ + 1, 2, 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, 0, 0, 0 + ] + }; let person = Person { first_name: "John", diff --git a/tooling/nargo_fmt/tests/expected/print.nr b/tooling/nargo_fmt/tests/expected/print.nr index e169f56545..3bce0941da 100644 --- a/tooling/nargo_fmt/tests/expected/print.nr +++ b/tooling/nargo_fmt/tests/expected/print.nr @@ -1,5 +1,6 @@ use dep::std; fn main() { + std::print("Hello world"); std::println("Hello world"); } diff --git a/tooling/nargo_fmt/tests/expected/print2.nr b/tooling/nargo_fmt/tests/expected/print2.nr index 80284444af..3bce0941da 100644 --- a/tooling/nargo_fmt/tests/expected/print2.nr +++ b/tooling/nargo_fmt/tests/expected/print2.nr @@ -1,5 +1,6 @@ use dep::std; -fn main( ) { +fn main() { + std::print("Hello world"); std::println("Hello world"); } diff --git a/tooling/nargo_fmt/tests/input/fn.nr b/tooling/nargo_fmt/tests/input/fn.nr index f503db9985..26ff593380 100644 --- a/tooling/nargo_fmt/tests/input/fn.nr +++ b/tooling/nargo_fmt/tests/input/fn.nr @@ -24,3 +24,23 @@ fn main(tape: [Field; TAPE_LEN], initial_registers: [Field; REGISTER_COUNT], ini fn apply_binary_field_op(lhs: RegisterIndex, rhs: RegisterIndex, result: RegisterIndex, op: u8, registers: &mut Registers) -> bool {} fn main() -> distinct pub [Field;2] {} + +fn ret_normal_lambda1() -> ((fn() -> Field)) {} + +fn ret_normal_lambda1() -> fn() -> Field {} + +fn ret_closure1() -> fn[(Field,)]() -> Field {} + +fn ret_closure2() -> fn[(Field,Field)]() -> Field {} + +fn ret_closure3() -> fn[(u32,u64)]() -> u64 {} + +fn make_counter() -> fn[(&mut Field,)]() -> Field {} + +fn get_some(generator: fn[Env]() -> Field) -> [Field;5] {} + +fn main( + message: [u8; 10], message_field: Field, pub_key_x: Field, pub_key_y: Field, signature: [u8; 64] +) {} + +pub fn from_baz(x: [Field; crate::foo::MAGIC_NUMBER]) {} diff --git a/tooling/nargo_fmt/tests/input/print.nr b/tooling/nargo_fmt/tests/input/print.nr index 8afa562dad..3bce0941da 100644 --- a/tooling/nargo_fmt/tests/input/print.nr +++ b/tooling/nargo_fmt/tests/input/print.nr @@ -1,3 +1,6 @@ use dep::std; -fn main() { std::println("Hello world"); } +fn main() { + std::print("Hello world"); + std::println("Hello world"); +} diff --git a/tooling/nargo_fmt/tests/input/print2.nr b/tooling/nargo_fmt/tests/input/print2.nr index 07ef9dd038..3bce0941da 100644 --- a/tooling/nargo_fmt/tests/input/print2.nr +++ b/tooling/nargo_fmt/tests/input/print2.nr @@ -1,5 +1,6 @@ use dep::std; -fn main( ) { -std::println("Hello world"); +fn main() { + std::print("Hello world"); + std::println("Hello world"); } diff --git a/tooling/nargo_toml/src/errors.rs b/tooling/nargo_toml/src/errors.rs index fdbdc317bf..da976e1b18 100644 --- a/tooling/nargo_toml/src/errors.rs +++ b/tooling/nargo_toml/src/errors.rs @@ -71,9 +71,10 @@ pub enum ManifestError { SemverError(SemverError), } +#[allow(clippy::enum_variant_names)] #[derive(Error, Debug, PartialEq, Eq, Clone)] pub enum SemverError { - #[error("Incompatible compiler version in package {package_name}. Required compiler version is {required_compiler_version} but the compiler version is {compiler_version_found}.\n Update the compiler_version field in Nargo.toml to >={compiler_version_found} or compile this project with version {compiler_version_found}")] + #[error("Incompatible compiler version in package {package_name}. Required compiler version is {required_compiler_version} but the compiler version is {compiler_version_found}.\n Update the compiler_version field in Nargo.toml to >={required_compiler_version} or compile this project with version {required_compiler_version}")] IncompatibleVersion { package_name: CrateName, required_compiler_version: String, @@ -81,4 +82,6 @@ pub enum SemverError { }, #[error("Could not parse the required compiler version for package {package_name} in Nargo.toml. Error: {error}")] CouldNotParseRequiredVersion { package_name: String, error: String }, + #[error("Could not parse the package version for package {package_name} in Nargo.toml. Error: {error}")] + CouldNotParsePackageVersion { package_name: String, error: String }, } diff --git a/tooling/nargo_toml/src/lib.rs b/tooling/nargo_toml/src/lib.rs index 223ed2da08..56024f8ed4 100644 --- a/tooling/nargo_toml/src/lib.rs +++ b/tooling/nargo_toml/src/lib.rs @@ -8,6 +8,7 @@ use std::{ path::{Component, Path, PathBuf}, }; +use errors::SemverError; use fm::{NormalizePath, FILE_EXTENSION}; use nargo::{ package::{Dependency, Package, PackageType}, @@ -23,6 +24,27 @@ mod semver; pub use errors::ManifestError; use git::clone_git_repo; +/// Searches for a `Nargo.toml` file in the current directory and all parent directories. +/// For example, if the current directory is `/workspace/package/src`, then this function +/// will search for a `Nargo.toml` file in +/// * `/workspace/package/src`, +/// * `/workspace/package`, +/// * `/workspace`. +/// +/// Returns the [PathBuf] of the `Nargo.toml` file if found, otherwise returns None. +/// +/// It will return innermost `Nargo.toml` file, which is the one closest to the current directory. +/// For example, if the current directory is `/workspace/package/src`, then this function +/// will return the `Nargo.toml` file in `/workspace/package/Nargo.toml` +pub fn find_file_manifest(current_path: &Path) -> Option { + for path in current_path.ancestors() { + if let Ok(toml_path) = get_package_manifest(path) { + return Some(toml_path); + } + } + None +} + /// Returns the [PathBuf] of the directory containing the `Nargo.toml` by searching from `current_path` to the root of its [Path]. /// /// Returns a [ManifestError] if no parent directories of `current_path` contain a manifest file. @@ -99,7 +121,7 @@ struct PackageConfig { impl PackageConfig { fn resolve_to_package(&self, root_dir: &Path) -> Result { - let name = if let Some(name) = &self.package.name { + let name: CrateName = if let Some(name) = &self.package.name { name.parse().map_err(|_| ManifestError::InvalidPackageName { toml: root_dir.join("Nargo.toml"), name: name.into(), @@ -163,7 +185,18 @@ impl PackageConfig { } }; + // If there is a package version, ensure that it is semver compatible + if let Some(version) = &self.package.version { + semver::parse_semver_compatible_version(version).map_err(|err| { + ManifestError::SemverError(SemverError::CouldNotParsePackageVersion { + package_name: name.to_string(), + error: err.to_string(), + }) + })?; + } + Ok(Package { + version: self.package.version.clone(), compiler_required_version: self.package.compiler_version.clone(), root_dir: root_dir.to_path_buf(), entry_path, @@ -225,6 +258,7 @@ struct WorkspaceConfig { #[derive(Default, Debug, Deserialize, Clone)] struct PackageMetadata { name: Option, + version: Option, #[serde(alias = "type")] package_type: Option, entry: Option, @@ -398,7 +432,7 @@ pub fn resolve_workspace_from_toml( let nargo_toml = read_toml(toml_path)?; let workspace = toml_to_workspace(nargo_toml, package_selection)?; if let Some(current_compiler_version) = current_compiler_version { - semver::semver_check_workspace(workspace.clone(), current_compiler_version)?; + semver::semver_check_workspace(&workspace, current_compiler_version)?; } Ok(workspace) } diff --git a/tooling/nargo_toml/src/semver.rs b/tooling/nargo_toml/src/semver.rs index de722f06bd..7c6e2a18b3 100644 --- a/tooling/nargo_toml/src/semver.rs +++ b/tooling/nargo_toml/src/semver.rs @@ -3,14 +3,19 @@ use nargo::{ package::{Dependency, Package}, workspace::Workspace, }; -use semver::{Version, VersionReq}; +use semver::{Error, Version, VersionReq}; + +// Parse a semver compatible version string +pub(crate) fn parse_semver_compatible_version(version: &str) -> Result { + Version::parse(version) +} // Check that all of the packages in the workspace are compatible with the current compiler version pub(crate) fn semver_check_workspace( - workspace: Workspace, + workspace: &Workspace, current_compiler_version: String, ) -> Result<(), ManifestError> { - let version = Version::parse(¤t_compiler_version) + let version = parse_semver_compatible_version(¤t_compiler_version) .expect("The compiler version is not a valid semver version"); for package in &workspace.members { semver_check_package(package, &version).map_err(ManifestError::SemverError)?; @@ -83,6 +88,7 @@ mod tests { entry_path: PathBuf::new(), name: CrateName::from_str("test").unwrap(), dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), }; if let Err(err) = semver_check_package(&package, &compiler_version) { panic!("semver check should have passed. compiler version is 0.1.0 and required version from the package is 0.1.0\n error: {err:?}") @@ -113,6 +119,7 @@ mod tests { entry_path: PathBuf::new(), name: CrateName::from_str("test").unwrap(), dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), }; let valid_dependency = Package { @@ -122,6 +129,7 @@ mod tests { entry_path: PathBuf::new(), name: CrateName::from_str("good_dependency").unwrap(), dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), }; let invalid_dependency = Package { compiler_required_version: Some("0.2.0".to_string()), @@ -130,6 +138,7 @@ mod tests { entry_path: PathBuf::new(), name: CrateName::from_str("bad_dependency").unwrap(), dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), }; package.dependencies.insert( @@ -169,6 +178,7 @@ mod tests { entry_path: PathBuf::new(), name: CrateName::from_str("test").unwrap(), dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), }; if let Err(err) = semver_check_package(&package, &compiler_version) { @@ -187,6 +197,7 @@ mod tests { entry_path: PathBuf::new(), name: CrateName::from_str("test").unwrap(), dependencies: BTreeMap::new(), + version: Some("1.0".to_string()), }; if let Err(err) = semver_check_package(&package, &compiler_version) { diff --git a/tooling/noir_codegen/.gitignore b/tooling/noir_codegen/.gitignore index 721d05448d..15ea344d45 100644 --- a/tooling/noir_codegen/.gitignore +++ b/tooling/noir_codegen/.gitignore @@ -2,3 +2,4 @@ crs lib !test/*/target +test/codegen diff --git a/tooling/noir_codegen/package.json b/tooling/noir_codegen/package.json index 17772461df..52ad0321b8 100644 --- a/tooling/noir_codegen/package.json +++ b/tooling/noir_codegen/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.19.2", + "version": "0.20.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", @@ -26,8 +26,10 @@ "scripts": { "dev": "tsc-multi --watch", "build": "tsc", - "test": "ts-node --esm src/main.ts ./test/assert_lt/target/** --out-dir ./test/codegen && yarn test:node && rm -rf ./test/codegen", + "test": "yarn test:codegen && yarn test:node && yarn test:clean", + "test:codegen": "tsx src/main.ts ./test/assert_lt/target/** --out-dir ./test/codegen", "test:node": "mocha --timeout 25000 --exit --config ./.mocharc.json", + "test:clean": "rm -rf ./test/codegen", "prettier": "prettier 'src/**/*.ts'", "prettier:fix": "prettier --write 'src/**/*.ts' 'test/**/*.ts'", "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0", @@ -48,6 +50,7 @@ "mocha": "^10.2.0", "prettier": "3.0.3", "ts-node": "^10.9.1", + "tsx": "^4.6.2", "typescript": "^5.2.2" } } diff --git a/tooling/noir_codegen/src/index.ts b/tooling/noir_codegen/src/index.ts index 1f8d2d183d..8d45b76bd7 100644 --- a/tooling/noir_codegen/src/index.ts +++ b/tooling/noir_codegen/src/index.ts @@ -1,24 +1,56 @@ import { CompiledCircuit } from '@noir-lang/types'; +import { PrimitiveTypesUsed, generateTsInterface } from './noir_types.js'; -const codegenImports = `import { InputMap, InputValue } from "@noir-lang/noirc_abi" -import { Noir } from "@noir-lang/noir_js"`; +// TODO: reenable this. See `abiTypeToTs` for reasoning. +// export type FixedLengthArray = L extends 0 ? never[]: T[] & { length: L }; + +const codegenPrelude = `/* Autogenerated file, do not edit! */ + +/* eslint-disable */ + +import { Noir, InputMap, CompiledCircuit } from "@noir-lang/noir_js" +`; const codegenFunction = ( name: string, compiled_program: CompiledCircuit, -) => `export async function ${name}(args: InputMap): Promise { - const program = new Noir(${JSON.stringify(compiled_program)}); + function_signature: { inputs: [string, string][]; returnValue: string | null }, +) => { + const args = function_signature.inputs.map(([name]) => `${name}`).join(', '); + const args_with_types = function_signature.inputs.map(([name, type]) => `${name}: ${type}`).join(', '); + + return ` +export const ${name}_circuit: CompiledCircuit = ${JSON.stringify(compiled_program)}; + +export async function ${name}(${args_with_types}): Promise<${function_signature.returnValue}> { + const program = new Noir(${name}_circuit); + const args: InputMap = { ${args} }; const { returnValue } = await program.execute(args); - return returnValue; + return returnValue as ${function_signature.returnValue}; }`; +}; export const codegen = (programs: [string, CompiledCircuit][]): string => { - const results = [codegenImports]; + let results = [codegenPrelude]; + const primitiveTypeMap = new Map(); + + const functions: string[] = []; for (const [name, program] of programs) { - results.push(codegenFunction(name, stripUnwantedFields(program))); + const [types_string, function_sig] = generateTsInterface(program.abi, primitiveTypeMap); + functions.push(types_string); + functions.push('\n'); + functions.push(codegenFunction(name, stripUnwantedFields(program), function_sig)); } - return results.join('\n\n'); + // Add the primitive Noir types that do not have a 1-1 mapping to TypeScript. + const primitiveTypeAliases: string[] = []; + for (const value of primitiveTypeMap.values()) { + primitiveTypeAliases.push(`export type ${value.aliasName} = ${value.tsType};`); + } + + results = results.concat(...primitiveTypeAliases, ...functions); + + return results.filter((val) => val !== '').join('\n'); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/tooling/noir_codegen/src/noir_types.ts b/tooling/noir_codegen/src/noir_types.ts new file mode 100644 index 0000000000..ba4f8650b3 --- /dev/null +++ b/tooling/noir_codegen/src/noir_types.ts @@ -0,0 +1,189 @@ +import { AbiType, Abi } from '@noir-lang/noirc_abi'; + +/** + * Keep track off all of the Noir primitive types that were used. + * Most of these will not have a 1-1 definition in TypeScript, + * so we will need to generate type aliases for them. + * + * We want to generate type aliases + * for specific types that are used in the ABI. + * + * For example: + * - If `Field` is used we want to alias that + * with `number`. + * - If `u32` is used we want to alias that with `number` too. + */ +export type PrimitiveTypesUsed = { + /** + * The name of the type alias that we will generate. + */ + aliasName: string; + /** + * The TypeScript type that we will alias to. + */ + tsType: string; +}; + +/** + * Typescript does not allow us to check for equality of non-primitive types + * easily, so we create a addIfUnique function that will only add an item + * to the map if it is not already there by using JSON.stringify. + * @param item - The item to add to the map. + */ +function addIfUnique(primitiveTypeMap: Map, item: PrimitiveTypesUsed) { + const key = JSON.stringify(item); + if (!primitiveTypeMap.has(key)) { + primitiveTypeMap.set(key, item); + } +} + +/** + * Converts an ABI type to a TypeScript type. + * @param type - The ABI type to convert. + * @returns The typescript code to define the type. + */ +function abiTypeToTs(type: AbiType, primitiveTypeMap: Map): string { + switch (type.kind) { + case 'field': + addIfUnique(primitiveTypeMap, { aliasName: 'Field', tsType: 'string' }); + return 'Field'; + case 'integer': { + const typeName = type.sign === 'signed' ? `i${type.width}` : `u${type.width}`; + // Javascript cannot safely represent the full range of Noir's integer types as numbers. + // `Number.MAX_SAFE_INTEGER == 2**53 - 1` so we disallow passing numbers to types which may exceed this. + // 52 has been chosen as the cutoff rather than 53 for safety. + const tsType = type.width <= 52 ? `string | number` : `string`; + + addIfUnique(primitiveTypeMap, { aliasName: typeName, tsType }); + return typeName; + } + case 'boolean': + return `boolean`; + case 'array': + // We can't force the usage of fixed length arrays as this currently throws errors in TS. + // The array would need to be `as const` to support this whereas that's unlikely to happen in user code. + // return `FixedLengthArray<${abiTypeToTs(type.type, primitiveTypeMap)}, ${type.length}>`; + return `${abiTypeToTs(type.type, primitiveTypeMap)}[]`; + case 'string': + // We could enforce that literals are the correct length but not generally. + // This would run into similar problems to above. + return `string`; + case 'struct': + return getLastComponentOfPath(type.path); + case 'tuple': { + const field_types = type.fields.map((field) => abiTypeToTs(field, primitiveTypeMap)); + return `[${field_types.join(', ')}]`; + } + default: + throw new Error(`Unknown ABI type ${JSON.stringify(type)}`); + } +} + +/** + * Returns the last component of a path, e.g. "foo::bar::baz" -\> "baz" + * Note: that if we have a path such as "Baz", we will return "Baz". + * + * Since these paths corresponds to structs, we can assume that we + * cannot have "foo::bar::". + * + * We also make the assumption that since these paths are coming from + * Noir, then we will not have two paths that look like this: + * - foo::bar::Baz + * - cat::dog::Baz + * ie the last component of the path (struct name) is enough to uniquely identify + * the whole path. + * + * TODO: We should double check this assumption when we use type aliases, + * I expect that `foo::bar::Baz as Dog` would effectively give `foo::bar::Dog` + * @param str - The path to get the last component of. + * @returns The last component of the path. + */ +function getLastComponentOfPath(str: string): string { + const parts = str.split('::'); + const lastPart = parts[parts.length - 1]; + return lastPart; +} + +/** + * Generates TypeScript interfaces for the structs used in the ABI. + * @param type - The ABI type to generate the interface for. + * @param output - The set of structs that we have already generated bindings for. + * @returns The TypeScript code to define the struct. + */ +function generateStructInterfaces( + type: AbiType, + output: Set, + primitiveTypeMap: Map, +): string { + let result = ''; + + // Edge case to handle the array of structs case. + if (type.kind === 'array' && type.type.kind === 'struct' && !output.has(getLastComponentOfPath(type.type.path))) { + result += generateStructInterfaces(type.type, output, primitiveTypeMap); + } + if (type.kind !== 'struct') return result; + + // List of structs encountered while viewing this type that we need to generate + // bindings for. + const typesEncountered = new Set(); + + // Codegen the struct and then its fields, so that the structs fields + // are defined before the struct itself. + let codeGeneratedStruct = ''; + let codeGeneratedStructFields = ''; + + const structName = getLastComponentOfPath(type.path); + if (!output.has(structName)) { + codeGeneratedStruct += `export type ${structName} = {\n`; + for (const field of type.fields) { + codeGeneratedStruct += ` ${field.name}: ${abiTypeToTs(field.type, primitiveTypeMap)};\n`; + typesEncountered.add(field.type); + } + codeGeneratedStruct += `};`; + output.add(structName); + + // Generate code for the encountered structs in the field above + for (const type of typesEncountered) { + codeGeneratedStructFields += generateStructInterfaces(type, output, primitiveTypeMap); + } + } + + return codeGeneratedStructFields + '\n' + codeGeneratedStruct; +} + +/** + * Generates a TypeScript interface for the ABI. + * @param abiObj - The ABI to generate the interface for. + * @returns The TypeScript code to define the interface. + */ +export function generateTsInterface( + abiObj: Abi, + primitiveTypeMap: Map, +): [string, { inputs: [string, string][]; returnValue: string | null }] { + let result = ``; + const outputStructs = new Set(); + + // Define structs for composite types + for (const param of abiObj.parameters) { + result += generateStructInterfaces(param.type, outputStructs, primitiveTypeMap); + } + + // Generating Return type, if it exists + if (abiObj.return_type != null) { + result += generateStructInterfaces(abiObj.return_type.abi_type, outputStructs, primitiveTypeMap); + } + + return [result, getTsFunctionSignature(abiObj, primitiveTypeMap)]; +} + +function getTsFunctionSignature( + abi: Abi, + primitiveTypeMap: Map, +): { inputs: [string, string][]; returnValue: string | null } { + const inputs: [string, string][] = abi.parameters.map((param) => [ + param.name, + abiTypeToTs(param.type, primitiveTypeMap), + ]); + const returnValue = abi.return_type ? abiTypeToTs(abi.return_type.abi_type, primitiveTypeMap) : null; + return { inputs, returnValue }; +} diff --git a/tooling/noir_codegen/test/assert_lt/src/main.nr b/tooling/noir_codegen/test/assert_lt/src/main.nr index 0698cbce4a..3b3e04ddec 100644 --- a/tooling/noir_codegen/test/assert_lt/src/main.nr +++ b/tooling/noir_codegen/test/assert_lt/src/main.nr @@ -1,4 +1,19 @@ -fn main(x: u64, y: pub u64) -> pub u64 { +struct MyStruct { + foo: bool, + bar: [str<5>; 3], +} + +fn main( + x: u64, + y: pub u64, + array: [u8; 5], + my_struct: MyStruct, + string: str<5> +) -> pub (u64, u64, MyStruct) { + assert(array.len() == 5); + assert(my_struct.foo); + assert(string == "12345"); + assert(x < y); - x + y + (x + y, 3, my_struct) } diff --git a/tooling/noir_codegen/test/assert_lt/target/assert_lt.json b/tooling/noir_codegen/test/assert_lt/target/assert_lt.json index 3b2b1b2c5a..a1ab87a99f 100644 --- a/tooling/noir_codegen/test/assert_lt/target/assert_lt.json +++ b/tooling/noir_codegen/test/assert_lt/target/assert_lt.json @@ -1 +1 @@ -{"hash":13834844072603749544,"backend":"acvm-backend-barretenberg","abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"}],"param_witnesses":{"x":[1],"y":[2]},"return_type":{"kind":"integer","sign":"unsigned","width":64},"return_witnesses":[12]},"bytecode":"H4sIAAAAAAAA/+1WUW6DMAx1QksZoGr72jUcAiX8VbvJ0Oj9j7ChJpKbtXw0NpvUWkImUXixn53w3gDgHc6mfh7t/ZGMtR9TU96HeYuHtp36ZjLWfGIzjK7DthsPzjjTue6rcdZOrnX9MA49Dqa1kzl1gz3h2bL7sTDCMhmJbylmTDOT8WEhjXfjH/DcB8u8zwVygWifmL/9lTnWzSWKsxHA3QJf00vlveWvERJIUU4x0eb86aEJppljVox9oO+Py8QTV1Jnw6a85t7vSL8pwvN89j7gd88o8q79Gr2wRt3AeSFz4XvRSyokl5MAtSfgGO2ZCewdsDibLRVrDzIXTMxfqiLIGXPeMdY1gb/Fg8+tznJY50eSGmfB2DNrqciCD+tCRc4X5FNFJmIWnkhu3BL+t4qc8y75aySqIkvGOP9CRWKaGQ0ydUrsgUUVWXlfw4OpyAouVWQN66pITDPDqSJfQaZxuVVkxZhzzVgLTv5uHbDwXhN+vwGywklHPBQAAA=="} \ No newline at end of file +{"noir_version":"0.19.4+55670ff82c270534a4bdb999ab0de5cea7017093","hash":11505576107297330043,"backend":"acvm-backend-barretenberg","abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"},{"name":"array","type":{"kind":"array","length":5,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"my_struct","type":{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]},"visibility":"private"},{"name":"string","type":{"kind":"string","length":5},"visibility":"private"}],"param_witnesses":{"array":[{"start":3,"end":8}],"my_struct":[{"start":8,"end":24}],"string":[{"start":24,"end":29}],"x":[{"start":1,"end":2}],"y":[{"start":2,"end":3}]},"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"integer","sign":"unsigned","width":64},{"kind":"integer","sign":"unsigned","width":64},{"kind":"struct","path":"MyStruct","fields":[{"name":"foo","type":{"kind":"boolean"}},{"name":"bar","type":{"kind":"array","length":3,"type":{"kind":"string","length":5}}}]}]},"visibility":"public"},"return_witnesses":[31,32,33,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]},"bytecode":"H4sIAAAAAAAA/81XbU/CMBDu5hv4gopvvGw49JOJH1q2wfaN+E+AddFEgzGL/H250Go5dInumnhJ0z2jXJ9er7s+t4yxe7YyZ9lc1Y8N7CK8tWw1A28jvIPwLsJ7Cus5mfIPxquZqBlzmX5DPowiORpIEYoJH6TTJOZRPB0mIhFxEmeDJAxlEiWjdJqOeCqiUIo8TsNcOa7RceQ6DnUUl32EDxA+RPgI4QbCxwifIHyKcBPhM4TPEb5A+BLhK4RbCLcR7iDcRdhjX3mjzUb+jIlyxibPFgFPmYNlVnm2yXjOcps8O3Q8pU2eXTqemU2eHh3PGdQbl22aS8zZYXRn3/07L4FffLN0Mt9mXH3V99iqhuu80GOgzj+wzZxxjGdXjXFLxjg/+Kkb7/T/G8bvVRe/EQxzciqfvgok9QXEp+P4eQHpGT61bRHHw9ahqurrhjCeZfH7JU+OeAqfcM09wn2tEL/SD9x/Pjdl+8yr2do54dVMUJ6Ta0b/3TF92tr3gI53aJNnn3DfuwZHyE8o2FDIQYBr0Q1FFoQmiEsQlCAiociCWASBCKIQhCCIPxB8IPJA2IGYA9EBF3q4LMNcHlsv/E31XGUOyI1g2fpsvfDfqd5T/aQo5MtrERTzYJJlweKpeAzm7/Itf54vPgBYg2KL1RAAAA=="} \ No newline at end of file diff --git a/tooling/noir_codegen/test/index.test.ts b/tooling/noir_codegen/test/index.test.ts index 702ba1f9cb..48199c13a6 100644 --- a/tooling/noir_codegen/test/index.test.ts +++ b/tooling/noir_codegen/test/index.test.ts @@ -1,11 +1,16 @@ import { expect } from 'chai'; -import { assert_lt } from './codegen/index.js'; +import { assert_lt, MyStruct, u64 } from './codegen/index.js'; it('codegens a callable function', async () => { - const result = await assert_lt({ - x: '2', - y: '3', - }); + const [sum, constant, struct]: [u64, u64, MyStruct] = await assert_lt( + '2', + '3', + [0, 0, 0, 0, 0], + { foo: true, bar: ['12345', '12345', '12345'] }, + '12345', + ); - expect(result).to.be.eq('0x05'); + expect(sum).to.be.eq('0x05'); + expect(constant).to.be.eq('0x03'); + expect(struct).to.be.deep.eq({ foo: true, bar: ['12345', '12345', '12345'] }); }); diff --git a/tooling/noir_js/.mocharc.json b/tooling/noir_js/.mocharc.json index c2e70b73d0..be7e952e7c 100644 --- a/tooling/noir_js/.mocharc.json +++ b/tooling/noir_js/.mocharc.json @@ -1,6 +1,5 @@ { - "require": "ts-node/register", - "loader": "ts-node/esm", + "require": "tsx", "extensions": ["ts", "cjs"], "spec": [ "test/node/**/*.test.ts*" diff --git a/tooling/noir_js/package.json b/tooling/noir_js/package.json index 51bc755020..e42cbb1d16 100644 --- a/tooling/noir_js/package.json +++ b/tooling/noir_js/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.19.2", + "version": "0.20.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", @@ -50,6 +50,7 @@ "prettier": "3.0.3", "ts-node": "^10.9.1", "tsc-multi": "^1.1.0", + "tsx": "^4.6.2", "typescript": "^5.2.2" } } diff --git a/tooling/noir_js/src/index.ts b/tooling/noir_js/src/index.ts index 5e700a5b58..bacb391a46 100644 --- a/tooling/noir_js/src/index.ts +++ b/tooling/noir_js/src/index.ts @@ -12,6 +12,7 @@ export { and, } from '@noir-lang/acvm_js'; +export { InputMap } from '@noir-lang/noirc_abi'; export { WitnessMap, ForeignCallHandler, ForeignCallInput, ForeignCallOutput } from '@noir-lang/acvm_js'; export { Noir } from './program.js'; diff --git a/tooling/noir_js/src/program.ts b/tooling/noir_js/src/program.ts index 711413bbc8..809943727e 100644 --- a/tooling/noir_js/src/program.ts +++ b/tooling/noir_js/src/program.ts @@ -67,12 +67,12 @@ export class Noir { * * @example * ```typescript - * async generateFinalproof(input) + * async generateFinalProof(input) * ``` * */ - async generateFinalProof(inputs: InputMap): Promise { - const { witness } = await this.execute(inputs); + async generateFinalProof(inputs: InputMap, foreignCallHandler?: ForeignCallHandler): Promise { + const { witness } = await this.execute(inputs, foreignCallHandler); return this.getBackend().generateFinalProof(witness); } diff --git a/tooling/noir_js/src/witness_generation.ts b/tooling/noir_js/src/witness_generation.ts index e3ddb1a2a2..a329c79c91 100644 --- a/tooling/noir_js/src/witness_generation.ts +++ b/tooling/noir_js/src/witness_generation.ts @@ -3,7 +3,14 @@ import { base64Decode } from './base64_decode.js'; import { executeCircuit, WitnessMap, ForeignCallHandler, ForeignCallInput } from '@noir-lang/acvm_js'; import { CompiledCircuit } from '@noir-lang/types'; -const defaultForeignCallHandler: ForeignCallHandler = (name: string, args: ForeignCallInput[]) => { +const defaultForeignCallHandler: ForeignCallHandler = async (name: string, args: ForeignCallInput[]) => { + if (name == 'print') { + // By default we do not print anything for `print` foreign calls due to a need for formatting, + // however we provide an empty response in order to not halt execution. + // + // If a user needs to print values then they should provide a custom foreign call handler. + return []; + } throw Error(`Unexpected oracle during execution: ${name}(${args.join(', ')})`); }; diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr b/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr index 0698cbce4a..693e728573 100644 --- a/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr +++ b/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr @@ -1,4 +1,9 @@ +use dep::std; + fn main(x: u64, y: pub u64) -> pub u64 { + // We include a println statement to show that noirJS will ignore this and continue execution + std::println("foo"); + assert(x < y); x + y } diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_lt/target/assert_lt.json b/tooling/noir_js/test/noir_compiled_examples/assert_lt/target/assert_lt.json index c01b2c5d3f..5b511cdc14 100644 --- a/tooling/noir_js/test/noir_compiled_examples/assert_lt/target/assert_lt.json +++ b/tooling/noir_js/test/noir_compiled_examples/assert_lt/target/assert_lt.json @@ -1 +1 @@ -{"hash":13834844072603749544,"backend":"acvm-backend-barretenberg","abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"}],"param_witnesses":{"x":[{ "start": 1, "end": 2 }],"y":[{ "start": 2, "end": 3 }]},"return_type":{"kind":"integer","sign":"unsigned","width":64},"return_witnesses":[12]},"bytecode":"H4sIAAAAAAAA/+1WUW6DMAx1QksZoGr72jUcAiX8VbvJ0Oj9j7ChJpKbtXw0NpvUWkImUXixn53w3gDgHc6mfh7t/ZGMtR9TU96HeYuHtp36ZjLWfGIzjK7DthsPzjjTue6rcdZOrnX9MA49Dqa1kzl1gz3h2bL7sTDCMhmJbylmTDOT8WEhjXfjH/DcB8u8zwVygWifmL/9lTnWzSWKsxHA3QJf00vlveWvERJIUU4x0eb86aEJppljVox9oO+Py8QTV1Jnw6a85t7vSL8pwvN89j7gd88o8q79Gr2wRt3AeSFz4XvRSyokl5MAtSfgGO2ZCewdsDibLRVrDzIXTMxfqiLIGXPeMdY1gb/Fg8+tznJY50eSGmfB2DNrqciCD+tCRc4X5FNFJmIWnkhu3BL+t4qc8y75aySqIkvGOP9CRWKaGQ0ydUrsgUUVWXlfw4OpyAouVWQN66pITDPDqSJfQaZxuVVkxZhzzVgLTv5uHbDwXhN+vwGywklHPBQAAA=="} \ No newline at end of file +{"noir_version":"0.20.0+010fdb69616f47fc0a9f252a65a903316d3cbe80","hash":17538653710107541030,"backend":"acvm-backend-barretenberg","abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"}],"param_witnesses":{"x":[{"start":1,"end":2}],"y":[{"start":2,"end":3}]},"return_type":{"abi_type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"},"return_witnesses":[5]},"bytecode":"H4sIAAAAAAAA/9Wa627aMBiGHcKhBBLOR+0Hl+Ak5PQP9U6gBK3SNqoqWm9kFzzMYu2DujhbPjvFEkrsJu/7vJ+TFDAtQkiH/GnG6VXLtxvQr+V9Mx/jx5pE3Db5lpZqYahI96Ba91e+bee1g60J6objS90mehbqN8nfuUbSpLAeNVAjXg++bZxeD/m+k9esjlyz6+t3A/p1MFfYvkyzharpPrXzmsFmXPU3YL8F8jUV5HvA1aRMs42qGe2YhgVqwuvH2Tvg721QLwu5Xgbw5Lq8bynz9Tye8Vb+joCjozF/R5lveJ7/riR/V8DR1Zi/q8w3TJiGLclvCzhsjfltZb5hyjQcSX5HwOFozO8o8w3XTKMnyd8TcPQ05od8RVmtilnxff0t0+hL8vcFHH2N+SFfUVarYlZ838hnGgNJ/oGAY6Ax/0CZb3R+rgwl+YcCjqHG/ENlvtH5fdVIkn8k4BhpzA/5irJ274jVrpgV3zeMmMZYkn8s4BhrzA/5irJaFbPi+3pPTGMiyT8RcEw05od8RVmtilnxfcPzXE0l+acCjqnG/FNlvmHANGaS/DMBx0xjfshXlNW+I9bRHbEOKmbF9w1jpjGX5J8LOOYa80O+oqzWHbH2KmbF9/XPnwUXkvwLAcdCY/6FMt9ozzSWkvxLAcdSY/4l8MVet3gAmV9en39kHKAOYPg+X2xlzQRjXOALOIeDtsj7hR60qpnk/eolAWNYPgbQ8k/fTK7TyEtd391SL9nFAV0HuzB2YzeIg70X+34ar+Mo2SURTdy1n7qHIPEPuVjt/7nc6wFBdDRtWFe46tgAE18D44/geLgCb4A5eQTniI4xPtBpgzF+vkMUXljQHEvTJJc/T+C6ZS8oE4+R8kmtk8vlWELwfxKg6qYqq9VErOet+v0jJ73idE3EzHXEeS1Rv5sPuM9839yaZ1quXdwntFxzMe+TBsF/7nDNj/6B8P0GuXz4848R/B3INsvS7y/ZKjuutvv96u05+7o6/kxfD9+Ob78Bhjydn08mAAA="} \ No newline at end of file diff --git a/tooling/noir_js_backend_barretenberg/.mocharc.json b/tooling/noir_js_backend_barretenberg/.mocharc.json new file mode 100644 index 0000000000..e1023f5632 --- /dev/null +++ b/tooling/noir_js_backend_barretenberg/.mocharc.json @@ -0,0 +1,11 @@ +{ + "require": "ts-node/register", + "loader": "ts-node/esm", + "extensions": [ + "ts", + "cjs" + ], + "spec": [ + "test/**/*.test.ts*" + ] +} diff --git a/tooling/noir_js_backend_barretenberg/package.json b/tooling/noir_js_backend_barretenberg/package.json index 13c64dc1d6..623a290410 100644 --- a/tooling/noir_js_backend_barretenberg/package.json +++ b/tooling/noir_js_backend_barretenberg/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.19.2", + "version": "0.20.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", @@ -25,6 +25,7 @@ "generate:package": "bash ./fixup.sh", "build": "yarn clean && tsc && tsc -p ./tsconfig.cjs.json && yarn generate:package", "clean": "rm -rf ./lib", + "test": "mocha --timeout 25000 --exit --config ./.mocharc.json", "prettier": "prettier 'src/**/*.ts'", "prettier:fix": "prettier --write 'src/**/*.ts' 'test/**/*.ts'", "nightly:version": "jq --arg new_version \"-$(git rev-parse --short HEAD)$1\" '.version = .version + $new_version' package.json > package-tmp.json && mv package-tmp.json package.json", @@ -32,16 +33,19 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.12.0", + "@aztec/bb.js": "0.16.0", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, "devDependencies": { "@types/node": "^20.6.2", "@types/prettier": "^3", + "chai": "^4.3.8", "eslint": "^8.50.0", "eslint-plugin-prettier": "^5.0.0", + "mocha": "^10.2.0", "prettier": "3.0.3", + "ts-node": "^10.9.1", "typescript": "5.1.5" } } diff --git a/tooling/noir_js_backend_barretenberg/src/index.ts b/tooling/noir_js_backend_barretenberg/src/index.ts index 820cda93c8..100418debd 100644 --- a/tooling/noir_js_backend_barretenberg/src/index.ts +++ b/tooling/noir_js_backend_barretenberg/src/index.ts @@ -3,6 +3,9 @@ import { decompressSync as gunzip } from 'fflate'; import { acirToUint8Array } from './serialize.js'; import { Backend, CompiledCircuit, ProofData } from '@noir-lang/types'; import { BackendOptions } from './types.js'; +import { deflattenPublicInputs, flattenPublicInputsAsArray } from './public_inputs.js'; + +export { flattenPublicInputs } from './public_inputs.js'; // This is the number of bytes in a UltraPlonk proof // minus the public inputs. @@ -18,7 +21,7 @@ export class BarretenbergBackend implements Backend { private acirUncompressedBytecode: Uint8Array; constructor( - acirCircuit: CompiledCircuit, + private acirCircuit: CompiledCircuit, private options: BackendOptions = { threads: 1 }, ) { const acirBytecodeBase64 = acirCircuit.bytecode; @@ -91,16 +94,8 @@ export class BarretenbergBackend implements Backend { const splitIndex = proofWithPublicInputs.length - numBytesInProofWithoutPublicInputs; const publicInputsConcatenated = proofWithPublicInputs.slice(0, splitIndex); - - const publicInputSize = 32; - const publicInputs: Uint8Array[] = []; - - for (let i = 0; i < publicInputsConcatenated.length; i += publicInputSize) { - const publicInput = publicInputsConcatenated.slice(i, i + publicInputSize); - publicInputs.push(publicInput); - } - const proof = proofWithPublicInputs.slice(splitIndex); + const publicInputs = deflattenPublicInputs(publicInputsConcatenated, this.acirCircuit.abi); return { proof, publicInputs }; } @@ -185,7 +180,7 @@ export class BarretenbergBackend implements Backend { function reconstructProofWithPublicInputs(proofData: ProofData): Uint8Array { // Flatten publicInputs - const publicInputsConcatenated = flattenUint8Arrays(proofData.publicInputs); + const publicInputsConcatenated = flattenPublicInputsAsArray(proofData.publicInputs); // Concatenate publicInputs and proof const proofWithPublicInputs = Uint8Array.from([...publicInputsConcatenated, ...proofData.proof]); @@ -193,18 +188,5 @@ function reconstructProofWithPublicInputs(proofData: ProofData): Uint8Array { return proofWithPublicInputs; } -function flattenUint8Arrays(arrays: Uint8Array[]): Uint8Array { - const totalLength = arrays.reduce((acc, val) => acc + val.length, 0); - const result = new Uint8Array(totalLength); - - let offset = 0; - for (const arr of arrays) { - result.set(arr, offset); - offset += arr.length; - } - - return result; -} - // typedoc exports export { Backend, BackendOptions, CompiledCircuit, ProofData }; diff --git a/tooling/noir_js_backend_barretenberg/src/public_inputs.ts b/tooling/noir_js_backend_barretenberg/src/public_inputs.ts new file mode 100644 index 0000000000..37bc5b1301 --- /dev/null +++ b/tooling/noir_js_backend_barretenberg/src/public_inputs.ts @@ -0,0 +1,89 @@ +import { Abi, WitnessMap } from '@noir-lang/types'; + +export function flattenPublicInputs(publicInputs: WitnessMap): string[] { + const publicInputIndices = [...publicInputs.keys()].sort((a, b) => a - b); + const flattenedPublicInputs = publicInputIndices.map((index) => publicInputs.get(index) as string); + return flattenedPublicInputs; +} + +export function flattenPublicInputsAsArray(publicInputs: WitnessMap): Uint8Array { + const flatPublicInputs = flattenPublicInputs(publicInputs); + const flattenedPublicInputs = flatPublicInputs.map(hexToUint8Array); + return flattenUint8Arrays(flattenedPublicInputs); +} + +export function deflattenPublicInputs(flattenedPublicInputs: Uint8Array, abi: Abi): WitnessMap { + const publicInputSize = 32; + const chunkedFlattenedPublicInputs: Uint8Array[] = []; + + for (let i = 0; i < flattenedPublicInputs.length; i += publicInputSize) { + const publicInput = flattenedPublicInputs.slice(i, i + publicInputSize); + chunkedFlattenedPublicInputs.push(publicInput); + } + + const return_value_witnesses = abi.return_witnesses; + const public_parameters = abi.parameters.filter((param) => param.visibility === 'public'); + const public_parameter_witnesses: number[] = public_parameters.flatMap((param) => + abi.param_witnesses[param.name].flatMap((witness_range) => + Array.from({ length: witness_range.end - witness_range.start }, (_, i) => witness_range.start + i), + ), + ); + + // We now have an array of witness indices which have been deduplicated and sorted in ascending order. + // The elements of this array should correspond to the elements of `flattenedPublicInputs` so that we can build up a `WitnessMap`. + const public_input_witnesses = [...new Set(public_parameter_witnesses.concat(return_value_witnesses))].sort( + (a, b) => a - b, + ); + + const publicInputs: WitnessMap = new Map(); + public_input_witnesses.forEach((witness_index, index) => { + const witness_value = uint8ArrayToHex(chunkedFlattenedPublicInputs[index]); + publicInputs.set(witness_index, witness_value); + }); + + return publicInputs; +} + +function flattenUint8Arrays(arrays: Uint8Array[]): Uint8Array { + const totalLength = arrays.reduce((acc, val) => acc + val.length, 0); + const result = new Uint8Array(totalLength); + + let offset = 0; + for (const arr of arrays) { + result.set(arr, offset); + offset += arr.length; + } + + return result; +} + +function uint8ArrayToHex(buffer: Uint8Array): string { + const hex: string[] = []; + + buffer.forEach(function (i) { + let h = i.toString(16); + if (h.length % 2) { + h = '0' + h; + } + hex.push(h); + }); + + return '0x' + hex.join(''); +} + +function hexToUint8Array(hex: string): Uint8Array { + const sanitised_hex = BigInt(hex).toString(16).padStart(64, '0'); + + const len = sanitised_hex.length / 2; + const u8 = new Uint8Array(len); + + let i = 0; + let j = 0; + while (i < len) { + u8[i] = parseInt(sanitised_hex.slice(j, j + 2), 16); + i += 1; + j += 2; + } + + return u8; +} diff --git a/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts b/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts new file mode 100644 index 0000000000..dab1c56436 --- /dev/null +++ b/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts @@ -0,0 +1,96 @@ +import { Abi } from '@noir-lang/types'; +import { expect } from 'chai'; +import { flattenPublicInputsAsArray, deflattenPublicInputs, flattenPublicInputs } from '../src/public_inputs.js'; + +const abi: Abi = { + parameters: [ + { + name: 'array_with_returned_element', + type: { + kind: 'array', + type: { + kind: 'field', + }, + length: 10, + }, + visibility: 'private', + }, + { + name: 'pub_field', + type: { + kind: 'field', + }, + visibility: 'public', + }, + ], + param_witnesses: { + array_with_returned_element: [ + { + start: 1, + end: 11, + }, + ], + pub_field: [ + { + start: 11, + end: 12, + }, + ], + }, + return_type: { + abi_type: { + kind: 'tuple', + fields: [ + { + kind: 'field', + }, + { + kind: 'field', + }, + { + kind: 'field', + }, + ], + }, + visibility: 'public', + }, + return_witnesses: [2, 13, 13], +}; + +it('flattens a witness map in order of its witness indices', async () => { + // Note that these are not in ascending order. This means that if we read from `witness_map` in insertion order + // then the witness values will be sorted incorrectly. + const public_input_indices = [2, 13, 11]; + + const witness_map = new Map( + public_input_indices.map((witness_index) => [ + witness_index, + '0x' + BigInt(witness_index).toString(16).padStart(64, '0'), + ]), + ); + + const flattened_public_inputs = flattenPublicInputs(witness_map); + expect(flattened_public_inputs).to.be.deep.eq([ + '0x0000000000000000000000000000000000000000000000000000000000000002', + '0x000000000000000000000000000000000000000000000000000000000000000b', + '0x000000000000000000000000000000000000000000000000000000000000000d', + ]); +}); + +it('recovers the original witness map when deflattening a public input array', async () => { + // Note that these are not in ascending order. This means that if we read from `witness_map` in insertion order + // then the witness values will be sorted incorrectly. + const public_input_indices = [2, 13, 11]; + + const witness_map = new Map( + public_input_indices.map((witness_index) => [ + witness_index, + '0x' + BigInt(witness_index).toString(16).padStart(64, '0'), + ]), + ); + + const flattened_public_inputs = flattenPublicInputsAsArray(witness_map); + const deflattened_public_inputs = deflattenPublicInputs(flattened_public_inputs, abi); + + expect(deflattened_public_inputs).to.be.deep.eq(witness_map); +}); diff --git a/tooling/noir_js_types/package.json b/tooling/noir_js_types/package.json index 3d74d33516..b322b9b620 100644 --- a/tooling/noir_js_types/package.json +++ b/tooling/noir_js_types/package.json @@ -4,7 +4,7 @@ "The Noir Team " ], "packageManager": "yarn@3.5.1", - "version": "0.19.2", + "version": "0.20.0", "license": "(MIT OR Apache-2.0)", "files": [ "lib", @@ -19,7 +19,8 @@ "build": "yarn run build:cjs && yarn run build:esm", "nightly:version": "jq --arg new_version \"-$(git rev-parse --short HEAD)$1\" '.version = .version + $new_version' package.json > package-tmp.json && mv package-tmp.json package.json", "publish": "echo 📡 publishing `$npm_package_name` && yarn npm publish", - "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" + "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0", + "clean": "rm -rf ./lib" }, "exports": { ".": { diff --git a/tooling/noir_js_types/src/types.ts b/tooling/noir_js_types/src/types.ts index 5ed6b1721e..b997d92425 100644 --- a/tooling/noir_js_types/src/types.ts +++ b/tooling/noir_js_types/src/types.ts @@ -1,4 +1,6 @@ -import { Abi } from '@noir-lang/noirc_abi'; +import { Abi, WitnessMap } from '@noir-lang/noirc_abi'; + +export { Abi, WitnessMap } from '@noir-lang/noirc_abi'; export interface Backend { /** @@ -43,7 +45,7 @@ export interface Backend { * */ export type ProofData = { /** @description Public inputs of a proof */ - publicInputs: Uint8Array[]; + publicInputs: WitnessMap; /** @description An byte array representing the proof */ proof: Uint8Array; }; diff --git a/tooling/noirc_abi/src/input_parser/json.rs b/tooling/noirc_abi/src/input_parser/json.rs index e2b1a83ee6..7618cd6c15 100644 --- a/tooling/noirc_abi/src/input_parser/json.rs +++ b/tooling/noirc_abi/src/input_parser/json.rs @@ -28,8 +28,11 @@ pub(crate) fn parse_json( if let (Some(return_type), Some(json_return_value)) = (&abi.return_type, data.get(MAIN_RETURN_NAME)) { - let return_value = - InputValue::try_from_json(json_return_value.clone(), return_type, MAIN_RETURN_NAME)?; + let return_value = InputValue::try_from_json( + json_return_value.clone(), + &return_type.abi_type, + MAIN_RETURN_NAME, + )?; parsed_inputs.insert(MAIN_RETURN_NAME.to_owned(), return_value); } @@ -48,7 +51,7 @@ pub(crate) fn serialize_to_json( if let (Some(return_type), Some(return_value)) = (&abi.return_type, input_map.get(MAIN_RETURN_NAME)) { - let return_value = JsonTypes::try_from_input_value(return_value, return_type)?; + let return_value = JsonTypes::try_from_input_value(return_value, &return_type.abi_type)?; json_map.insert(MAIN_RETURN_NAME.to_owned(), return_value); } diff --git a/tooling/noirc_abi/src/input_parser/mod.rs b/tooling/noirc_abi/src/input_parser/mod.rs index 7bbcb42296..26c5a89c83 100644 --- a/tooling/noirc_abi/src/input_parser/mod.rs +++ b/tooling/noirc_abi/src/input_parser/mod.rs @@ -130,7 +130,8 @@ mod serialization_tests { use strum::IntoEnumIterator; use crate::{ - input_parser::InputValue, Abi, AbiParameter, AbiType, AbiVisibility, Sign, MAIN_RETURN_NAME, + input_parser::InputValue, Abi, AbiParameter, AbiReturnType, AbiType, AbiVisibility, Sign, + MAIN_RETURN_NAME, }; use super::Format; @@ -159,7 +160,10 @@ mod serialization_tests { visibility: AbiVisibility::Private, }, ], - return_type: Some(AbiType::String { length: 5 }), + return_type: Some(AbiReturnType { + abi_type: AbiType::String { length: 5 }, + visibility: AbiVisibility::Public, + }), // These two fields are unused when serializing/deserializing to file. param_witnesses: BTreeMap::new(), return_witnesses: Vec::new(), @@ -293,7 +297,6 @@ mod test { #[test] fn rejects_noncanonical_fields() { let noncanonical_field = FieldElement::modulus().to_string(); - let parsed_field = parse_str_to_field(&noncanonical_field); - println!("{parsed_field:?}"); + assert!(parse_str_to_field(&noncanonical_field).is_err()); } } diff --git a/tooling/noirc_abi/src/input_parser/toml.rs b/tooling/noirc_abi/src/input_parser/toml.rs index 645b59b00c..b216fe5879 100644 --- a/tooling/noirc_abi/src/input_parser/toml.rs +++ b/tooling/noirc_abi/src/input_parser/toml.rs @@ -28,8 +28,11 @@ pub(crate) fn parse_toml( if let (Some(return_type), Some(toml_return_value)) = (&abi.return_type, data.get(MAIN_RETURN_NAME)) { - let return_value = - InputValue::try_from_toml(toml_return_value.clone(), return_type, MAIN_RETURN_NAME)?; + let return_value = InputValue::try_from_toml( + toml_return_value.clone(), + &return_type.abi_type, + MAIN_RETURN_NAME, + )?; parsed_inputs.insert(MAIN_RETURN_NAME.to_owned(), return_value); } @@ -48,7 +51,7 @@ pub(crate) fn serialize_to_toml( if let (Some(return_type), Some(return_value)) = (&abi.return_type, input_map.get(MAIN_RETURN_NAME)) { - let return_value = TomlTypes::try_from_input_value(return_value, return_type)?; + let return_value = TomlTypes::try_from_input_value(return_value, &return_type.abi_type)?; toml_map.insert(MAIN_RETURN_NAME.to_owned(), return_value); } diff --git a/tooling/noirc_abi/src/lib.rs b/tooling/noirc_abi/src/lib.rs index 7092f05c26..884c49c010 100644 --- a/tooling/noirc_abi/src/lib.rs +++ b/tooling/noirc_abi/src/lib.rs @@ -78,6 +78,7 @@ pub enum AbiVisibility { // Constants are not allowed in the ABI for main at the moment. // Constant, Private, + DataBus, } impl From for AbiVisibility { @@ -85,6 +86,7 @@ impl From for AbiVisibility { match value { Visibility::Public => AbiVisibility::Public, Visibility::Private => AbiVisibility::Private, + Visibility::DataBus => AbiVisibility::DataBus, } } } @@ -94,6 +96,7 @@ impl From<&Visibility> for AbiVisibility { match value { Visibility::Public => AbiVisibility::Public, Visibility::Private => AbiVisibility::Private, + Visibility::DataBus => AbiVisibility::DataBus, } } } @@ -158,7 +161,7 @@ impl AbiType { Type::Error => unreachable!(), Type::Unit => unreachable!(), Type::Constant(_) => unreachable!(), - Type::TraitAsType(_) => unreachable!(), + Type::TraitAsType(..) => unreachable!(), Type::Struct(def, ref args) => { let struct_type = def.borrow(); let fields = struct_type.get_fields(args); @@ -212,6 +215,11 @@ impl AbiParameter { } } +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct AbiReturnType { + pub abi_type: AbiType, + pub visibility: AbiVisibility, +} #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Abi { /// An ordered list of the arguments to the program's `main` function, specifying their types and visibility. @@ -219,7 +227,7 @@ pub struct Abi { /// A map from the ABI's parameters to the indices they are written to in the [`WitnessMap`]. /// This defines how to convert between the [`InputMap`] and [`WitnessMap`]. pub param_witnesses: BTreeMap>>, - pub return_type: Option, + pub return_type: Option, pub return_witnesses: Vec, } @@ -327,7 +335,7 @@ impl Abi { // When encoding public inputs to be passed to the verifier, the user can must provide a return value // to be inserted into the witness map. This is not needed when generating a witness when proving the circuit. match (&self.return_type, return_value) { - (Some(return_type), Some(return_value)) => { + (Some(AbiReturnType { abi_type: return_type, .. }), Some(return_value)) => { if !return_value.matches_abi(return_type) { return Err(AbiError::ReturnTypeMismatch { return_type: return_type.clone(), @@ -426,7 +434,7 @@ impl Abi { .copied() }) { - Some(decode_value(&mut return_witness_values.into_iter(), return_type)?) + Some(decode_value(&mut return_witness_values.into_iter(), &return_type.abi_type)?) } else { // Unlike for the circuit inputs, we tolerate not being able to find the witness values for the return value. // This is because the user may be decoding a partial witness map for which is hasn't been calculated yet. @@ -546,7 +554,10 @@ mod test { use acvm::{acir::native_types::Witness, FieldElement}; - use crate::{input_parser::InputValue, Abi, AbiParameter, AbiType, AbiVisibility, InputMap}; + use crate::{ + input_parser::InputValue, Abi, AbiParameter, AbiReturnType, AbiType, AbiVisibility, + InputMap, + }; #[test] fn witness_encoding_roundtrip() { @@ -568,7 +579,10 @@ mod test { ("thing1".to_string(), vec![(Witness(1)..Witness(3))]), ("thing2".to_string(), vec![(Witness(3)..Witness(4))]), ]), - return_type: Some(AbiType::Field), + return_type: Some(AbiReturnType { + abi_type: AbiType::Field, + visibility: AbiVisibility::Public, + }), return_witnesses: vec![Witness(3)], }; diff --git a/tooling/noirc_abi_wasm/build.sh b/tooling/noirc_abi_wasm/build.sh index 37f2fd0a5a..24af149bce 100755 --- a/tooling/noirc_abi_wasm/build.sh +++ b/tooling/noirc_abi_wasm/build.sh @@ -34,7 +34,7 @@ export CARGO_TARGET_DIR=$self_path/target rm -rf $self_path/outputs >/dev/null 2>&1 rm -rf $self_path/result >/dev/null 2>&1 -if [ -v out ]; then +if [ -n "$out" ]; then echo "Will install package to $out (defined outside installPhase.sh script)" else export out="$self_path/outputs/out" diff --git a/tooling/noirc_abi_wasm/package.json b/tooling/noirc_abi_wasm/package.json index d307a186a7..fe801a40d5 100644 --- a/tooling/noirc_abi_wasm/package.json +++ b/tooling/noirc_abi_wasm/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.19.2", + "version": "0.20.0", "license": "(MIT OR Apache-2.0)", "files": [ "nodejs", diff --git a/tooling/noirc_abi_wasm/src/lib.rs b/tooling/noirc_abi_wasm/src/lib.rs index 734ca1ff40..fb4c295b8c 100644 --- a/tooling/noirc_abi_wasm/src/lib.rs +++ b/tooling/noirc_abi_wasm/src/lib.rs @@ -47,7 +47,7 @@ extern "C" { #[wasm_bindgen(typescript_custom_section)] const ABI: &'static str = r#" -export type Visibility = "public" | "private"; +export type Visibility = "public" | "private" | "databus"; export type Sign = "unsigned" | "signed"; export type AbiType = { kind: "field" } | @@ -56,7 +56,7 @@ export type AbiType = { kind: "integer", sign: Sign, width: number } | { kind: "array", length: number, type: AbiType } | { kind: "tuple", fields: AbiType[] } | - { kind: "struct", path: string, fields: [string, AbiType][] }; + { kind: "struct", path: string, fields: { name: string, type: AbiType }[] }; export type AbiParameter = { name: string, @@ -67,7 +67,7 @@ export type AbiParameter = { export type Abi = { parameters: AbiParameter[], param_witnesses: Record, - return_type: AbiType | null, + return_type: {abi_type: AbiType, visibility: Visibility} | null, return_witnesses: number[], } "#; @@ -96,7 +96,7 @@ pub fn abi_encode( .expect("could not decode return value"); InputValue::try_from_json( toml_return_value, - abi.return_type.as_ref().unwrap(), + &abi.return_type.as_ref().unwrap().abi_type, MAIN_RETURN_NAME, ) }) @@ -134,7 +134,7 @@ pub fn abi_decode(abi: JsAbi, witness_map: JsWitnessMap) -> Result=16" + react: ">=16" + checksum: a780cff9d7f7639d6fc21c9d4e0a6ac1370c3209ea0db176923df7f9145785309591cf871f227f5135d1fe2accce0d5df9a22fc0530e5dda0c7b4b105705f20d languageName: node linkType: hard @@ -3225,10 +3698,36 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:1.1.2": - version: 1.1.2 - resolution: "@noble/hashes@npm:1.1.2" - checksum: 3c2a8cb7c2e053811032f242155d870c5eb98844d924d69702244d48804cb03b42d4a666c49c2b71164420d8229cb9a6f242b972d50d5bb2f1d673b98b041de2 +"@monaco-editor/loader@npm:^1.4.0": + version: 1.4.0 + resolution: "@monaco-editor/loader@npm:1.4.0" + dependencies: + state-local: ^1.0.6 + peerDependencies: + monaco-editor: ">= 0.21.0 < 1" + checksum: 374ec0ea872ee15b33310e105a43217148161480d3955c5cece87d0f801754cd2c45a3f6c539a75da18a066c1615756fb87eaf1003f1df6a64a0cbce5d2c3749 + languageName: node + linkType: hard + +"@monaco-editor/react@npm:4.6.0": + version: 4.6.0 + resolution: "@monaco-editor/react@npm:4.6.0" + dependencies: + "@monaco-editor/loader": ^1.4.0 + peerDependencies: + monaco-editor: ">= 0.25.0 < 1" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: 9d44e76c5baad6db5f84c90a5540fbd3c9af691b97d76cf2a99b3c8273004d0efe44c2572d80e9d975c9af10022c21e4a66923924950a5201e82017c8b20428c + languageName: node + linkType: hard + +"@noble/curves@npm:1.2.0": + version: 1.2.0 + resolution: "@noble/curves@npm:1.2.0" + dependencies: + "@noble/hashes": 1.3.2 + checksum: bb798d7a66d8e43789e93bc3c2ddff91a1e19fdb79a99b86cd98f1e5eff0ee2024a2672902c2576ef3577b6f282f3b5c778bebd55761ddbb30e36bf275e83dd0 languageName: node linkType: hard @@ -3239,6 +3738,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:1.3.2": + version: 1.3.2 + resolution: "@noble/hashes@npm:1.3.2" + checksum: fe23536b436539d13f90e4b9be843cc63b1b17666a07634a2b1259dded6f490be3d050249e6af98076ea8f2ea0d56f578773c2197f2aa0eeaa5fba5bc18ba474 + languageName: node + linkType: hard + "@noble/secp256k1@npm:1.7.1, @noble/secp256k1@npm:~1.7.0": version: 1.7.1 resolution: "@noble/secp256k1@npm:1.7.1" @@ -3412,6 +3918,13 @@ __metadata: languageName: node linkType: hard +"@noir-lang/acvm_js@npm:0.35.0": + version: 0.35.0 + resolution: "@noir-lang/acvm_js@npm:0.35.0" + checksum: 0a2209f60242d9dbef31e72b738d70ff802da71f12d4b4f278144d373941f30844c8d041518970e71ba82eb9337cf4cc3a40fbd4b2c50acff45d84d2ee7dd435 + languageName: node + linkType: hard + "@noir-lang/acvm_js@workspace:*, @noir-lang/acvm_js@workspace:acvm-repo/acvm_js": version: 0.0.0-use.local resolution: "@noir-lang/acvm_js@workspace:acvm-repo/acvm_js" @@ -3430,18 +3943,32 @@ __metadata: languageName: unknown linkType: soft +"@noir-lang/backend_barretenberg@npm:^0.19.2": + version: 0.19.4 + resolution: "@noir-lang/backend_barretenberg@npm:0.19.4" + dependencies: + "@aztec/bb.js": 0.16.0 + "@noir-lang/types": 0.19.4 + fflate: ^0.8.0 + checksum: b84382e71f29f0e10415f8c3a68eb7bb0653f56df1b3e8afd66c22df7adc950fb9016124f32253abad3d05583bccf26b1d0c0cabc601218083fd27d0601a3c02 + languageName: node + linkType: hard + "@noir-lang/backend_barretenberg@workspace:*, @noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg": version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": 0.12.0 + "@aztec/bb.js": 0.16.0 "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 + chai: ^4.3.8 eslint: ^8.50.0 eslint-plugin-prettier: ^5.0.0 fflate: ^0.8.0 + mocha: ^10.2.0 prettier: 3.0.3 + ts-node: ^10.9.1 typescript: 5.1.5 languageName: unknown linkType: soft @@ -3466,12 +3993,24 @@ __metadata: prettier: 3.0.3 ts-command-line-args: ^2.5.1 ts-node: ^10.9.1 + tsx: ^4.6.2 typescript: ^5.2.2 bin: noir-codegen: lib/main.js languageName: unknown linkType: soft +"@noir-lang/noir_js@npm:^0.19.2": + version: 0.19.4 + resolution: "@noir-lang/noir_js@npm:0.19.4" + dependencies: + "@noir-lang/acvm_js": 0.35.0 + "@noir-lang/noirc_abi": 0.19.4 + "@noir-lang/types": 0.19.4 + checksum: 1ee6140019861cee3a27d511951e6b3ed629925a83328b0fbe18791a534c36d26d33ae3ca3aa25252fac8932dfeefedc0d5f07169d5d08f1485d6290965d2491 + languageName: node + linkType: hard + "@noir-lang/noir_js@workspace:*, @noir-lang/noir_js@workspace:tooling/noir_js": version: 0.0.0-use.local resolution: "@noir-lang/noir_js@workspace:tooling/noir_js" @@ -3490,10 +4029,20 @@ __metadata: prettier: 3.0.3 ts-node: ^10.9.1 tsc-multi: ^1.1.0 + tsx: ^4.6.2 typescript: ^5.2.2 languageName: unknown linkType: soft +"@noir-lang/noir_wasm@npm:^0.19.2": + version: 0.19.4 + resolution: "@noir-lang/noir_wasm@npm:0.19.4" + peerDependencies: + "@noir-lang/source-resolver": 0.19.4 + checksum: b69748240e27851f19b20b4ce1d0c57da7e9055b9d0e0c16f699338394912c00277e5586afcff77d3f6f08e17bbf1bc6253ff1ad156b8f4985c4435adad0ba49 + languageName: node + linkType: hard + "@noir-lang/noir_wasm@workspace:*, @noir-lang/noir_wasm@workspace:compiler/wasm": version: 0.0.0-use.local resolution: "@noir-lang/noir_wasm@workspace:compiler/wasm" @@ -3503,11 +4052,16 @@ __metadata: "@web/test-runner": ^0.15.3 "@web/test-runner-playwright": ^0.10.0 mocha: ^10.2.0 - peerDependencies: - "@noir-lang/source-resolver": "workspace:*" languageName: unknown linkType: soft +"@noir-lang/noirc_abi@npm:0.19.4": + version: 0.19.4 + resolution: "@noir-lang/noirc_abi@npm:0.19.4" + checksum: 7446127935c954ae1b2bfdfa6cf111a9c14a2024f13a2d7e7e0a612319b0b4cc199acdbceaa94168e3bd5d82760b9d2fd2c9eec6677d57ed76e7b666e2b28c7d + languageName: node + linkType: hard + "@noir-lang/noirc_abi@workspace:*, @noir-lang/noirc_abi@workspace:tooling/noirc_abi_wasm": version: 0.0.0-use.local resolution: "@noir-lang/noirc_abi@workspace:tooling/noirc_abi_wasm" @@ -3537,15 +4091,21 @@ __metadata: languageName: unknown linkType: soft -"@noir-lang/source-resolver@workspace:*, @noir-lang/source-resolver@workspace:compiler/source-resolver": - version: 0.0.0-use.local - resolution: "@noir-lang/source-resolver@workspace:compiler/source-resolver" +"@noir-lang/source-resolver@npm:^0.19.2": + version: 0.19.4 + resolution: "@noir-lang/source-resolver@npm:0.19.4" + checksum: f0e51bb54daa1197894a17e5d0d125481aa0872c49c0d955feec2629b8ff51b9b48144778def6539a87b723a9b4c5eacc79d6eb935f0da6a1893d8d403689683 + languageName: node + linkType: hard + +"@noir-lang/types@npm:0.19.4, @noir-lang/types@npm:^0.19.2": + version: 0.19.4 + resolution: "@noir-lang/types@npm:0.19.4" dependencies: - "@types/node": ^20.5.7 - ava: ^5.2.0 - typescript: 4.9.4 - languageName: unknown - linkType: soft + "@noir-lang/noirc_abi": 0.19.4 + checksum: 1d0ce99895c0bc98e9daf67028132f71e30f60b2dc0799ee99f311d917e84459a0d2a37c318f5ab14e594e7dd26f5e612e5fd9a7e0a20a692a7017d7c883bb4d + languageName: node + linkType: hard "@noir-lang/types@workspace:*, @noir-lang/types@workspace:tooling/noir_js_types": version: 0.0.0-use.local @@ -3736,15 +4296,15 @@ __metadata: linkType: hard "@nomicfoundation/hardhat-ethers@npm:^3.0.0": - version: 3.0.4 - resolution: "@nomicfoundation/hardhat-ethers@npm:3.0.4" + version: 3.0.5 + resolution: "@nomicfoundation/hardhat-ethers@npm:3.0.5" dependencies: debug: ^4.1.1 lodash.isequal: ^4.5.0 peerDependencies: ethers: ^6.1.0 hardhat: ^2.0.0 - checksum: 57cbb13682cf0e14cf5bb17b47a2004f69765358fffba7d660ab277a6aff38583216637aa3c5c68410a649a9cd41f774a8df2cb89098f6f616f6108c0f6e5d7a + checksum: 34b092dfec68f8d8673c96af717660327edc814bc5c9cdb5bc1f82d5bde2b18bc9b9d3499a632784a3d4f2505ac174217e55d31b546b7eaa77a5bb30b3c80bb4 languageName: node linkType: hard @@ -3857,6 +4417,19 @@ __metadata: languageName: node linkType: hard +"@npmcli/agent@npm:^2.0.0": + version: 2.2.0 + resolution: "@npmcli/agent@npm:2.2.0" + dependencies: + agent-base: ^7.1.0 + http-proxy-agent: ^7.0.0 + https-proxy-agent: ^7.0.1 + lru-cache: ^10.0.1 + socks-proxy-agent: ^8.0.1 + checksum: 3b25312edbdfaa4089af28e2d423b6f19838b945e47765b0c8174c1395c79d43c3ad6d23cb364b43f59fd3acb02c93e3b493f72ddbe3dfea04c86843a7311fc4 + languageName: node + linkType: hard + "@npmcli/fs@npm:^3.1.0": version: 3.1.0 resolution: "@npmcli/fs@npm:3.1.0" @@ -3873,7 +4446,7 @@ __metadata: languageName: node linkType: hard -"@pkgr/utils@npm:^2.3.1": +"@pkgr/utils@npm:^2.4.2": version: 2.4.2 resolution: "@pkgr/utils@npm:2.4.2" dependencies: @@ -3887,10 +4460,37 @@ __metadata: languageName: node linkType: hard +"@pnpm/config.env-replace@npm:^1.1.0": + version: 1.1.0 + resolution: "@pnpm/config.env-replace@npm:1.1.0" + checksum: a3d2b57e35eec9543d9eb085854f6e33e8102dac99fdef2fad2eebdbbfc345e93299f0c20e8eb61c1b4c7aa123bfd47c175678626f161cda65dd147c2b6e1fa0 + languageName: node + linkType: hard + +"@pnpm/network.ca-file@npm:^1.0.1": + version: 1.0.2 + resolution: "@pnpm/network.ca-file@npm:1.0.2" + dependencies: + graceful-fs: 4.2.10 + checksum: d8d0884646500576bd5390464d13db1bb9a62e32a1069293e5bddb2ad8354b354b7e2d2a35e12850025651e795e6a80ce9e601c66312504667b7e3ee7b52becc + languageName: node + linkType: hard + +"@pnpm/npm-conf@npm:^2.1.0": + version: 2.2.2 + resolution: "@pnpm/npm-conf@npm:2.2.2" + dependencies: + "@pnpm/config.env-replace": ^1.1.0 + "@pnpm/network.ca-file": ^1.0.1 + config-chain: ^1.1.11 + checksum: d64aa4464be584caa855eafa8f109509390489997e36d602d6215784e2973b896bef3968426bb00896cf4ae7d440fed2cee7bb4e0dbc90362f024ea3f9e27ab1 + languageName: node + linkType: hard + "@polka/url@npm:^1.0.0-next.20": - version: 1.0.0-next.23 - resolution: "@polka/url@npm:1.0.0-next.23" - checksum: 4b0330de1ceecd1002c7e7449094d0c41f2ed0e21765f4835ccc7b003f2f024ac557d503b9ffdf0918cf50b80d5b8c99dfc5a91927e7b3c468b09c6bb42a3c41 + version: 1.0.0-next.24 + resolution: "@polka/url@npm:1.0.0-next.24" + checksum: 00baec4458ac86ca27edf7ce807ccfad97cd1d4b67bdedaf3401a9e755757588f3331e891290d1deea52d88df2bf2387caf8d94a6835b614d5b37b638a688273 languageName: node linkType: hard @@ -4079,6 +4679,27 @@ __metadata: languageName: node linkType: hard +"@signorecello/noir_playground@npm:^0.6.0": + version: 0.6.0 + resolution: "@signorecello/noir_playground@npm:0.6.0" + dependencies: + "@monaco-editor/react": 4.6.0 + "@noir-lang/backend_barretenberg": ^0.19.2 + "@noir-lang/noir_js": ^0.19.2 + "@noir-lang/noir_wasm": ^0.19.2 + "@noir-lang/source-resolver": ^0.19.2 + "@noir-lang/types": ^0.19.2 + fflate: ^0.8.1 + js-base64: ^3.7.5 + monaco-editor: ^0.44.0 + monaco-editor-textmate: ^4.0.0 + monaco-textmate: ^3.0.1 + onigasm: ^2.2.5 + react-toastify: ^9.1.3 + checksum: a1fa6f5b6aded80ad8ecdf8841dbbcd70e2a3faa479bc39f8077d3e96d65ceab53488f278db1a991a6cc8c6ce63206cc1627fe87e683187941359251e67c48ed + languageName: node + linkType: hard + "@sinclair/typebox@npm:^0.27.8": version: 0.27.8 resolution: "@sinclair/typebox@npm:0.27.8" @@ -4093,6 +4714,31 @@ __metadata: languageName: node linkType: hard +"@sindresorhus/is@npm:^4.6.0": + version: 4.6.0 + resolution: "@sindresorhus/is@npm:4.6.0" + checksum: 83839f13da2c29d55c97abc3bc2c55b250d33a0447554997a85c539e058e57b8da092da396e252b11ec24a0279a0bed1f537fa26302209327060643e327f81d2 + languageName: node + linkType: hard + +"@sindresorhus/is@npm:^5.2.0": + version: 5.6.0 + resolution: "@sindresorhus/is@npm:5.6.0" + checksum: 2e6e0c3acf188dcd9aea0f324ac1b6ad04c9fc672392a7b5a1218512fcde066965797eba8b9fe2108657a504388bd4a6664e6e6602555168e828a6df08b9f10e + languageName: node + linkType: hard + +"@slorber/remark-comment@npm:^1.0.0": + version: 1.0.0 + resolution: "@slorber/remark-comment@npm:1.0.0" + dependencies: + micromark-factory-space: ^1.0.0 + micromark-util-character: ^1.1.0 + micromark-util-symbol: ^1.0.1 + checksum: c96f1533d09913c57381859966f10a706afd8eb680923924af1c451f3b72f22c31e394028d7535131c10f8682d3c60206da95c50fb4f016fbbd04218c853cc88 + languageName: node + linkType: hard + "@slorber/static-site-generator-webpack-plugin@npm:^4.0.7": version: 4.0.7 resolution: "@slorber/static-site-generator-webpack-plugin@npm:4.0.7" @@ -4244,7 +4890,7 @@ __metadata: languageName: node linkType: hard -"@svgr/webpack@npm:^6.2.1": +"@svgr/webpack@npm:^6.2.1, @svgr/webpack@npm:^6.5.1": version: 6.5.1 resolution: "@svgr/webpack@npm:6.5.1" dependencies: @@ -4269,10 +4915,12 @@ __metadata: languageName: node linkType: hard -"@tootallnate/once@npm:2": - version: 2.0.0 - resolution: "@tootallnate/once@npm:2.0.0" - checksum: ad87447820dd3f24825d2d947ebc03072b20a42bfc96cbafec16bff8bbda6c1a81fcb0be56d5b21968560c5359a0af4038a68ba150c3e1694fe4c109a063bed8 +"@szmarczak/http-timer@npm:^5.0.1": + version: 5.0.1 + resolution: "@szmarczak/http-timer@npm:5.0.1" + dependencies: + defer-to-connect: ^2.0.1 + checksum: fc9cb993e808806692e4a3337c90ece0ec00c89f4b67e3652a356b89730da98bc824273a6d67ca84d5f33cd85f317dcd5ce39d8cc0a2f060145a608a7cb8ce92 languageName: node linkType: hard @@ -4312,18 +4960,27 @@ __metadata: linkType: hard "@types/accepts@npm:*": - version: 1.3.5 - resolution: "@types/accepts@npm:1.3.5" + version: 1.3.7 + resolution: "@types/accepts@npm:1.3.7" dependencies: "@types/node": "*" - checksum: 590b7580570534a640510c071e09074cf63b5958b237a728f94322567350aea4d239f8a9d897a12b15c856b992ee4d7907e9812bb079886af2c00714e7fb3f60 + checksum: 7678cf74976e16093aff6e6f9755826faf069ac1e30179276158ce46ea246348ff22ca6bdd46cef08428881337d9ceefbf00bab08a7731646eb9fc9449d6a1e7 + languageName: node + linkType: hard + +"@types/acorn@npm:^4.0.0": + version: 4.0.6 + resolution: "@types/acorn@npm:4.0.6" + dependencies: + "@types/estree": "*" + checksum: 60e1fd28af18d6cb54a93a7231c7c18774a9a8739c9b179e9e8750dca631e10cbef2d82b02830ea3f557b1d121e6406441e9e1250bd492dc81d4b3456e76e4d4 languageName: node linkType: hard "@types/babel__code-frame@npm:^7.0.2": - version: 7.0.4 - resolution: "@types/babel__code-frame@npm:7.0.4" - checksum: eb4adb0a79c5cbf2d88ad087b2694a1e38749dc0056693e6125c17a3967fc8d4cc1eb33eab26d3dcaaa8995236cba4a088965cc3a115967545f2a01ee430c87f + version: 7.0.6 + resolution: "@types/babel__code-frame@npm:7.0.6" + checksum: 5325ab85d95e58fe84279757788ddb0de68bfd6814bc636e868f9ff7b5229915873f28847c4baf48fd3a4a460a73b4ea87bc9e1d78a3a5a60cfc7ca627a722c5 languageName: node linkType: hard @@ -4337,142 +4994,160 @@ __metadata: linkType: hard "@types/bn.js@npm:^5.1.0": - version: 5.1.2 - resolution: "@types/bn.js@npm:5.1.2" + version: 5.1.5 + resolution: "@types/bn.js@npm:5.1.5" dependencies: "@types/node": "*" - checksum: 8d9fdb43836646c2ecd445041de03e057f9b459885be57faee64104160487a63730b9f371e8ad7d33f360b3cc6dc0e323543962fc5fa296b92b322b946732be0 + checksum: c87b28c4af74545624f8a3dae5294b16aa190c222626e8d4b2e327b33b1a3f1eeb43e7a24d914a9774bca43d8cd6e1cb0325c1f4b3a244af6693a024e1d918e6 languageName: node linkType: hard "@types/body-parser@npm:*": - version: 1.19.3 - resolution: "@types/body-parser@npm:1.19.3" + version: 1.19.5 + resolution: "@types/body-parser@npm:1.19.5" dependencies: "@types/connect": "*" "@types/node": "*" - checksum: 932fa71437c275023799123680ef26ffd90efd37f51a1abe405e6ae6e5b4ad9511b7a3a8f5a12877ed1444a02b6286c0a137a98e914b3c61932390c83643cc2c + checksum: 1e251118c4b2f61029cc43b0dc028495f2d1957fe8ee49a707fb940f86a9bd2f9754230805598278fe99958b49e9b7e66eec8ef6a50ab5c1f6b93e1ba2aaba82 languageName: node linkType: hard "@types/bonjour@npm:^3.5.9": - version: 3.5.11 - resolution: "@types/bonjour@npm:3.5.11" + version: 3.5.13 + resolution: "@types/bonjour@npm:3.5.13" dependencies: "@types/node": "*" - checksum: 12fb86a1bb4a610f16ef6d7d68f85e7c31070029f02b6622073794a271e75abcf58230ed205a2ae23c53be2c08b9e507d3b91fa0dc9dfe76c4b1f5e19e9370cb + checksum: e827570e097bd7d625a673c9c208af2d1a22fa3885c0a1646533cf24394c839c3e5f60ac1bc60c0ddcc69c0615078c9fb2c01b42596c7c582d895d974f2409ee languageName: node linkType: hard "@types/chai-as-promised@npm:^7.1.3": - version: 7.1.6 - resolution: "@types/chai-as-promised@npm:7.1.6" + version: 7.1.8 + resolution: "@types/chai-as-promised@npm:7.1.8" dependencies: "@types/chai": "*" - checksum: f765dd249ae9384540f8e6402bd3a9f5e87b97f9078ef58f4b5ec15f7c3673e1f10f0089f819eceb20e00b3df40b7aae1bd44d2b8f4edbbedfcb33ce296f6791 + checksum: f0e5eab451b91bc1e289ed89519faf6591932e8a28d2ec9bbe95826eb73d28fe43713633e0c18706f3baa560a7d97e7c7c20dc53ce639e5d75bac46b2a50bf21 languageName: node linkType: hard "@types/chai@npm:*, @types/chai@npm:^4, @types/chai@npm:^4.2.12": - version: 4.3.6 - resolution: "@types/chai@npm:4.3.6" - checksum: 32a6c18bf53fb3dbd89d1bfcadb1c6fd45cc0007c34e436393cc37a0a5a556f9e6a21d1e8dd71674c40cc36589d2f30bf4d9369d7787021e54d6e997b0d7300a + version: 4.3.11 + resolution: "@types/chai@npm:4.3.11" + checksum: d0c05fe5d02b2e6bbca2bd4866a2ab20a59cf729bc04af0060e7a3277eaf2fb65651b90d4c74b0ebf1d152b4b1d49fa8e44143acef276a2bbaa7785fbe5642d3 languageName: node linkType: hard "@types/co-body@npm:^6.1.0": - version: 6.1.1 - resolution: "@types/co-body@npm:6.1.1" + version: 6.1.3 + resolution: "@types/co-body@npm:6.1.3" dependencies: "@types/node": "*" "@types/qs": "*" - checksum: 38a5198c712bfb40f36c7c5fd85964cabfdac0d0aa4d703993c205ccafa113995b67846e59d5d05415dcba230e21126060e04c1287d8073fc2dc71257cb2ea0c + checksum: e93fdc177f69ee0535cf401783258e4255f5eb8235c58b5a2a5a8958cf341fadf3d0bf2c75907ed6b7d188ce2c2f2cf9593a71d4eef12900beba54ebbbdd5cc1 languageName: node linkType: hard "@types/command-line-args@npm:^5.0.0": - version: 5.2.1 - resolution: "@types/command-line-args@npm:5.2.1" - checksum: a5df8562a7a0eb7c4da218661360ff8369a63c0fd783310d1940f0ece55826d5173eeb3732bab48dbfb60b1614d61989a9d87c6cdbee04353c4df6f45387d417 + version: 5.2.3 + resolution: "@types/command-line-args@npm:5.2.3" + checksum: 3d90db5b4bbaabd049654a0d12fa378989ab0d76a0f98d4c606761b5a08ce76458df0f9bb175219e187b4cd57e285e6f836d23e86b2c3d997820854cc3ed9121 languageName: node linkType: hard "@types/connect-history-api-fallback@npm:^1.3.5": - version: 1.5.1 - resolution: "@types/connect-history-api-fallback@npm:1.5.1" + version: 1.5.4 + resolution: "@types/connect-history-api-fallback@npm:1.5.4" dependencies: "@types/express-serve-static-core": "*" "@types/node": "*" - checksum: bc5e46663300eba56eaf8ef242156256e2bdadc52bb7d6543f4b37f2945b6a810901c245711f8321fce7d94c7b588b308a86519f3e1f87a80eb87841d808dbdc + checksum: e1dee43b8570ffac02d2d47a2b4ba80d3ca0dd1840632dafb221da199e59dbe3778d3d7303c9e23c6b401f37c076935a5bc2aeae1c4e5feaefe1c371fe2073fd languageName: node linkType: hard "@types/connect@npm:*": - version: 3.4.36 - resolution: "@types/connect@npm:3.4.36" + version: 3.4.38 + resolution: "@types/connect@npm:3.4.38" dependencies: "@types/node": "*" - checksum: 4dee3d966fb527b98f0cbbdcf6977c9193fc3204ed539b7522fe5e64dfa45f9017bdda4ffb1f760062262fce7701a0ee1c2f6ce2e50af36c74d4e37052303172 + checksum: 7eb1bc5342a9604facd57598a6c62621e244822442976c443efb84ff745246b10d06e8b309b6e80130026a396f19bf6793b7cecd7380169f369dac3bfc46fb99 languageName: node linkType: hard "@types/content-disposition@npm:*": - version: 0.5.6 - resolution: "@types/content-disposition@npm:0.5.6" - checksum: da07798d52cc8fc46a8843d768b48d54c70f1a44c861dc2c73c4c25a1e08af859709629ab0e4d23d5198107b8926bb48c593df436ba68123d87191f5e25fe4bc + version: 0.5.8 + resolution: "@types/content-disposition@npm:0.5.8" + checksum: eeea868fb510ae7a32aa2d7de680fba79d59001f3e758a334621e10bc0a6496d3a42bb79243a5e53b9c63cb524522853ccc144fe1ab160c4247d37cdb81146c4 languageName: node linkType: hard "@types/convert-source-map@npm:^2.0.0": - version: 2.0.1 - resolution: "@types/convert-source-map@npm:2.0.1" - checksum: 200b2792b37748e89e4363ef07686b074f64e21a26f27381d51bc336222a85503cfa1266e29d3b9c9121c8156e0a3973f3adbe2f4be59516fa255c080b4ca976 + version: 2.0.3 + resolution: "@types/convert-source-map@npm:2.0.3" + checksum: 411cf9a02cf5dbe204e325dd5ebf50de00b58b38d1d2a3064c6ea28417c23bae956206eaa9ed3a75a994909b4ab3f9c6389073d0636a62500fa6d6333c64d45a languageName: node linkType: hard "@types/cookies@npm:*": - version: 0.7.8 - resolution: "@types/cookies@npm:0.7.8" + version: 0.7.10 + resolution: "@types/cookies@npm:0.7.10" dependencies: "@types/connect": "*" "@types/express": "*" "@types/keygrip": "*" "@types/node": "*" - checksum: 7945b0cfe370bf1f05a1f328c9eba55333dac1bb9d7efa3148b107c260ab924263546351f9fd168daa72948d195464d395319a24477995f9f887a3a99fbcb5b5 + checksum: 99cd44a193398932ff7926cfaac1eb4441d3dc47c3f64fdfb28861acbeb290b6db6a20376f993defc9d302db92bb1d36189b89ba447a633f960535f3f0d34e2d languageName: node linkType: hard "@types/debounce@npm:^1.2.0": - version: 1.2.1 - resolution: "@types/debounce@npm:1.2.1" - checksum: bea6d414acefbee50adfe87cee10f8a855d033e4778567ab03bdc3cb2648b6bf9237ca53f4ee76fe4be75f77f86d4688411499626fe409bc870f53631d24231f + version: 1.2.4 + resolution: "@types/debounce@npm:1.2.4" + checksum: decef3eee65d681556d50f7fac346f1b33134f6b21f806d41326f9dfb362fa66b0282ff0640ae6791b690694c9dc3dad4e146e909e707e6f96650f3aa325b9da + languageName: node + linkType: hard + +"@types/debug@npm:^4.0.0": + version: 4.1.12 + resolution: "@types/debug@npm:4.1.12" + dependencies: + "@types/ms": "*" + checksum: 47876a852de8240bfdaf7481357af2b88cb660d30c72e73789abf00c499d6bc7cd5e52f41c915d1b9cd8ec9fef5b05688d7b7aef17f7f272c2d04679508d1053 languageName: node linkType: hard "@types/eslint-scope@npm:^3.7.3": - version: 3.7.5 - resolution: "@types/eslint-scope@npm:3.7.5" + version: 3.7.7 + resolution: "@types/eslint-scope@npm:3.7.7" dependencies: "@types/eslint": "*" "@types/estree": "*" - checksum: e91ce335c3791c2cf6084caa0073f90d5b7ae3fcf27785ade8422b7d896159fa14a5a3f1efd31ef03e9ebc1ff04983288280dfe8c9a5579a958539f59df8cc9f + checksum: e2889a124aaab0b89af1bab5959847c5bec09809209255de0e63b9f54c629a94781daa04adb66bffcdd742f5e25a17614fb933965093c0eea64aacda4309380e languageName: node linkType: hard "@types/eslint@npm:*": - version: 8.44.4 - resolution: "@types/eslint@npm:8.44.4" + version: 8.44.8 + resolution: "@types/eslint@npm:8.44.8" dependencies: "@types/estree": "*" "@types/json-schema": "*" - checksum: 15bafdaba800e2995f38d3a2a929d8e9303035315e8d3535523a21cd719b6769a45884afa955f0b845ffa545a4150429b0178e2c44feeedf59ebb285eeae9825 + checksum: c3bc70166075e6e9f7fb43978882b9ac0b22596b519900b08dc8a1d761bbbddec4c48a60cc4eb674601266223c6f11db30f3fb6ceaae96c23c54b35ad88022bc + languageName: node + linkType: hard + +"@types/estree-jsx@npm:^1.0.0": + version: 1.0.3 + resolution: "@types/estree-jsx@npm:1.0.3" + dependencies: + "@types/estree": "*" + checksum: 6887a134308b6db4a33a147b56c9d0a47c17ea7e810bdd7c498c306a0fd00bcf2619cb0f57f74009d03dda974b3cd7e414767f85332b1d1b2be30a3ef9e1cca9 languageName: node linkType: hard "@types/estree@npm:*, @types/estree@npm:^1.0.0": - version: 1.0.2 - resolution: "@types/estree@npm:1.0.2" - checksum: aeedb1b2fe20cbe06f44b99b562bf9703e360bfcdf5bb3d61d248182ee1dd63500f2474e12f098ffe1f5ac3202b43b3e18ec99902d9328d5374f5512fa077e45 + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a languageName: node linkType: hard @@ -4483,51 +5158,27 @@ __metadata: languageName: node linkType: hard -"@types/express-serve-static-core@npm:*": - version: 4.17.37 - resolution: "@types/express-serve-static-core@npm:4.17.37" - dependencies: - "@types/node": "*" - "@types/qs": "*" - "@types/range-parser": "*" - "@types/send": "*" - checksum: 2dab1380e45eb44e56ecc1be1c42c4b897364d2f2a08e03ca28fbcb1e6866e390217385435813711c046f9acd684424d088855dc32825d5cbecf72c60ecd037f - languageName: node - linkType: hard - -"@types/express-serve-static-core@npm:^4.17.33": - version: 4.17.36 - resolution: "@types/express-serve-static-core@npm:4.17.36" +"@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33": + version: 4.17.41 + resolution: "@types/express-serve-static-core@npm:4.17.41" dependencies: "@types/node": "*" "@types/qs": "*" "@types/range-parser": "*" "@types/send": "*" - checksum: 410b13cbd663f18c0f8729e7f2ff54d960d96de76ebbae7cadb612972f85cc66c54051e00d32f11aa230c0a683d81a6d6fc7f7e4e383a95c0801494c517f36e1 - languageName: node - linkType: hard - -"@types/express@npm:*": - version: 4.17.17 - resolution: "@types/express@npm:4.17.17" - dependencies: - "@types/body-parser": "*" - "@types/express-serve-static-core": ^4.17.33 - "@types/qs": "*" - "@types/serve-static": "*" - checksum: 0196dacc275ac3ce89d7364885cb08e7fb61f53ca101f65886dbf1daf9b7eb05c0943e2e4bbd01b0cc5e50f37e0eea7e4cbe97d0304094411ac73e1b7998f4da + checksum: 12750f6511dd870bbaccfb8208ad1e79361cf197b147f62a3bedc19ec642f3a0f9926ace96705f4bc88ec2ae56f61f7ca8c2438e6b22f5540842b5569c28a121 languageName: node linkType: hard -"@types/express@npm:^4.17.13": - version: 4.17.19 - resolution: "@types/express@npm:4.17.19" +"@types/express@npm:*, @types/express@npm:^4.17.13": + version: 4.17.21 + resolution: "@types/express@npm:4.17.21" dependencies: "@types/body-parser": "*" "@types/express-serve-static-core": ^4.17.33 "@types/qs": "*" "@types/serve-static": "*" - checksum: 3d39d0655eb0825d96fec100985a38737767ddd6da2dbda1e330a3adf36c98a9b7cd8d9539db32876d1fbb47a09343cad7b38c30c8dd7c291271fcb9b85cb21b + checksum: fb238298630370a7392c7abdc80f495ae6c716723e114705d7e3fb67e3850b3859bbfd29391463a3fb8c0b32051847935933d99e719c0478710f8098ee7091c5 languageName: node linkType: hard @@ -4540,12 +5191,28 @@ __metadata: languageName: node linkType: hard +"@types/gtag.js@npm:^0.0.12": + version: 0.0.12 + resolution: "@types/gtag.js@npm:0.0.12" + checksum: 34efc27fbfd0013255b8bfd4af38ded9d5a6ba761130c76f17fd3a9585d83acc88d8005aab667cfec4bdec0e7c7217f689739799a8f61aed0edb929be58b162e + languageName: node + linkType: hard + "@types/hast@npm:^2.0.0": - version: 2.3.6 - resolution: "@types/hast@npm:2.3.6" + version: 2.3.8 + resolution: "@types/hast@npm:2.3.8" dependencies: "@types/unist": ^2 - checksum: c004372f6ab919ec92a2de43e4380707e27b76fe371c7d06ab26547c1e851dfba2a7c740c544218df8c7e0a94443458793c43730ad563a39e3fdc1a48904d7f5 + checksum: 4c3b3efb7067d32a568a9bf5d2a7599f99ec08c2eaade3aaeb579b7a31bcdf8f6475f56c1ac5bc3f4e4e07b84a93a9b1cf1ef9a8b52b39e3deabea7989e5dd4b + languageName: node + linkType: hard + +"@types/hast@npm:^3.0.0": + version: 3.0.3 + resolution: "@types/hast@npm:3.0.3" + dependencies: + "@types/unist": "*" + checksum: ca204207550fd6848ee20b5ba2018fd54f515d59a8b80375cdbe392ba2b4b130dac25fdfbaf9f2a70d2aec9d074a34dc14d4d59d31fa3ede80ef9850afad5d3c languageName: node linkType: hard @@ -4564,71 +5231,78 @@ __metadata: linkType: hard "@types/http-assert@npm:*": - version: 1.5.3 - resolution: "@types/http-assert@npm:1.5.3" - checksum: 9553e5a0b8bcfdac4b51d3fa3b89a91b5450171861a667a5b4c47204e0f4a1ca865d97396e6ceaf220e87b64d06b7a8bad7bfba15ef97acb41a87507c9940dbc + version: 1.5.5 + resolution: "@types/http-assert@npm:1.5.5" + checksum: cd6bb7fd42cc6e2a702cb55370b8b25231954ad74c04bcd185b943a74ded3d4c28099c30f77b26951df2426441baff41718816c60b5af80efe2b8888d900bf93 + languageName: node + linkType: hard + +"@types/http-cache-semantics@npm:^4.0.2": + version: 4.0.4 + resolution: "@types/http-cache-semantics@npm:4.0.4" + checksum: 7f4dd832e618bc1e271be49717d7b4066d77c2d4eed5b81198eb987e532bb3e1c7e02f45d77918185bad936f884b700c10cebe06305f50400f382ab75055f9e8 languageName: node linkType: hard "@types/http-errors@npm:*": - version: 2.0.2 - resolution: "@types/http-errors@npm:2.0.2" - checksum: d7f14045240ac4b563725130942b8e5c8080bfabc724c8ff3f166ea928ff7ae02c5194763bc8f6aaf21897e8a44049b0492493b9de3e058247e58fdfe0f86692 + version: 2.0.4 + resolution: "@types/http-errors@npm:2.0.4" + checksum: 1f3d7c3b32c7524811a45690881736b3ef741bf9849ae03d32ad1ab7062608454b150a4e7f1351f83d26a418b2d65af9bdc06198f1c079d75578282884c4e8e3 languageName: node linkType: hard "@types/http-proxy@npm:^1.17.8": - version: 1.17.12 - resolution: "@types/http-proxy@npm:1.17.12" + version: 1.17.14 + resolution: "@types/http-proxy@npm:1.17.14" dependencies: "@types/node": "*" - checksum: 89700c8e3c8f2c59c87c8db8e7a070c97a3b30a4a38223aca6b8b817e6f2ca931f5a500e16ecadc1ebcfed2676cc60e073d8f887e621d84420298728ec6fd000 + checksum: 491320bce3565bbb6c7d39d25b54bce626237cfb6b09e60ee7f77b56ae7c6cbad76f08d47fe01eaa706781124ee3dfad9bb737049254491efd98ed1f014c4e83 languageName: node linkType: hard "@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1, @types/istanbul-lib-coverage@npm:^2.0.3": - version: 2.0.4 - resolution: "@types/istanbul-lib-coverage@npm:2.0.4" - checksum: a25d7589ee65c94d31464c16b72a9dc81dfa0bea9d3e105ae03882d616e2a0712a9c101a599ec482d297c3591e16336962878cb3eb1a0a62d5b76d277a890ce7 + version: 2.0.6 + resolution: "@types/istanbul-lib-coverage@npm:2.0.6" + checksum: 3feac423fd3e5449485afac999dcfcb3d44a37c830af898b689fadc65d26526460bedb889db278e0d4d815a670331796494d073a10ee6e3a6526301fe7415778 languageName: node linkType: hard "@types/istanbul-lib-report@npm:*": - version: 3.0.0 - resolution: "@types/istanbul-lib-report@npm:3.0.0" + version: 3.0.3 + resolution: "@types/istanbul-lib-report@npm:3.0.3" dependencies: "@types/istanbul-lib-coverage": "*" - checksum: 656398b62dc288e1b5226f8880af98087233cdb90100655c989a09f3052b5775bf98ba58a16c5ae642fb66c61aba402e07a9f2bff1d1569e3b306026c59f3f36 + checksum: b91e9b60f865ff08cb35667a427b70f6c2c63e88105eadd29a112582942af47ed99c60610180aa8dcc22382fa405033f141c119c69b95db78c4c709fbadfeeb4 languageName: node linkType: hard "@types/istanbul-reports@npm:^3.0.0": - version: 3.0.1 - resolution: "@types/istanbul-reports@npm:3.0.1" + version: 3.0.4 + resolution: "@types/istanbul-reports@npm:3.0.4" dependencies: "@types/istanbul-lib-report": "*" - checksum: f1ad54bc68f37f60b30c7915886b92f86b847033e597f9b34f2415acdbe5ed742fa559a0a40050d74cdba3b6a63c342cac1f3a64dba5b68b66a6941f4abd7903 + checksum: 93eb18835770b3431f68ae9ac1ca91741ab85f7606f310a34b3586b5a34450ec038c3eed7ab19266635499594de52ff73723a54a72a75b9f7d6a956f01edee95 languageName: node linkType: hard "@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": - version: 7.0.13 - resolution: "@types/json-schema@npm:7.0.13" - checksum: 345df21a678fa72fb389f35f33de77833d09d4a142bb2bcb27c18690efa4cf70fc2876e43843cefb3fbdb9fcb12cd3e970a90936df30f53bbee899865ff605ab + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98 languageName: node linkType: hard -"@types/katex@npm:^0.11.0": - version: 0.11.1 - resolution: "@types/katex@npm:0.11.1" - checksum: 1e51988b4b386a1b6fa8e22826ab4705bf3e6c9fb03461f2c91d28cb31095232bdeff491069ac9bc74bc4c26110be6a11a41e12ca77a2e4169f3afd8cd349355 +"@types/katex@npm:^0.16.0": + version: 0.16.7 + resolution: "@types/katex@npm:0.16.7" + checksum: 4fd15d93553be97c02c064e16be18d7ccbabf66ec72a9dc7fd5bfa47f0c7581da2f942f693c7cb59499de4c843c2189796e49c9647d336cbd52b777b6722a95a languageName: node linkType: hard "@types/keygrip@npm:*": - version: 1.0.3 - resolution: "@types/keygrip@npm:1.0.3" - checksum: adee9a3efda3db9c64466af1c7c91a6d049420ee50589500cfd36e3e38d6abefdd858da88e6da63ed186e588127af3e862c1dc64fb0ad45c91870e6c35fe3be0 + version: 1.0.6 + resolution: "@types/keygrip@npm:1.0.6" + checksum: d157f60bf920492347791d2b26d530d5069ce05796549fbacd4c24d66ffbebbcb0ab67b21e7a1b80a593b9fd4b67dc4843dec04c12bbc2e0fddfb8577a826c41 languageName: node linkType: hard @@ -4642,17 +5316,17 @@ __metadata: linkType: hard "@types/koa-compose@npm:*": - version: 3.2.6 - resolution: "@types/koa-compose@npm:3.2.6" + version: 3.2.8 + resolution: "@types/koa-compose@npm:3.2.8" dependencies: "@types/koa": "*" - checksum: 1204c5bfa4c69448b692aba29c566ef6bedbdbe5842fa180450267a23d3606faa13ef209876fd0c989edb5bc381812a66610fcfeac196ce4e76364354756ba1f + checksum: 95c32bdee738ac7c10439bbf6342ca3b9f0aafd7e8118739eac7fb0fa703a23cfe4c88f63e13a69a16fbde702e0bcdc62b272aa734325fc8efa7e5625479752e languageName: node linkType: hard "@types/koa@npm:*, @types/koa@npm:^2.11.6": - version: 2.13.9 - resolution: "@types/koa@npm:2.13.9" + version: 2.13.12 + resolution: "@types/koa@npm:2.13.12" dependencies: "@types/accepts": "*" "@types/content-disposition": "*" @@ -4662,14 +5336,14 @@ __metadata: "@types/keygrip": "*" "@types/koa-compose": "*" "@types/node": "*" - checksum: af9cd599c8e17e2ae0f4168a61d964e343f713d002b65fd995658d7addc6551ccadecfd32b3405cf44e4d360178ee4f972d6881533548261ae1f636a655d24b1 + checksum: 4a2e7e19bf91779d0a3c46b8838d6faba5ee0e9a888e5ef8683722c21aa8efcf35f86d1a661adb56ca9f239f7724e306055e33bfa1b2dc008b9c0fa9fcc12bee languageName: node linkType: hard "@types/lodash@npm:^4": - version: 4.14.200 - resolution: "@types/lodash@npm:4.14.200" - checksum: 6471f8bb5da692a6ecf03a8da4935bfbc341e67ee9bcb4f5730bfacff0c367232548f0a01e8ac5ea18c6fe78fb085d502494e33ccb47a7ee87cbdee03b47d00d + version: 4.14.202 + resolution: "@types/lodash@npm:4.14.202" + checksum: a91acf3564a568c6f199912f3eb2c76c99c5a0d7e219394294213b3f2d54f672619f0fde4da22b29dc5d4c31457cd799acc2e5cb6bd90f9af04a1578483b6ff7 languageName: node linkType: hard @@ -4681,39 +5355,55 @@ __metadata: linkType: hard "@types/mdast@npm:^3.0.0": - version: 3.0.13 - resolution: "@types/mdast@npm:3.0.13" + version: 3.0.15 + resolution: "@types/mdast@npm:3.0.15" dependencies: "@types/unist": ^2 - checksum: f13fa17a2931ed1492a2f0012a3abd6de3a2d1128145981321909e03fedba80162668f284a4af92aca3732b27e933c5f4772336d96b9ae660bfde696d07abbe6 + checksum: af85042a4e3af3f879bde4059fa9e76c71cb552dffc896cdcc6cf9dc1fd38e37035c2dbd6245cfa6535b433f1f0478f5549696234ccace47a64055a10c656530 + languageName: node + linkType: hard + +"@types/mdast@npm:^4.0.0, @types/mdast@npm:^4.0.2": + version: 4.0.3 + resolution: "@types/mdast@npm:4.0.3" + dependencies: + "@types/unist": "*" + checksum: 345c5a22fccf05f35239ea6313ee4aaf6ebed5927c03ac79744abccb69b9ba5e692f9b771e36a012b79e17429082cada30f579e9c43b8a54e0ffb365431498b6 + languageName: node + linkType: hard + +"@types/mdx@npm:^2.0.0": + version: 2.0.10 + resolution: "@types/mdx@npm:2.0.10" + checksum: 3e2fb24b7bfae739a59573344171292b6c31256ad9afddc00232e9de4fbc97b270e1a11d13cb935cba0d9bbb9bc7348793eda82ee752233c5d2289f4b897f719 languageName: node linkType: hard "@types/mime@npm:*": - version: 3.0.1 - resolution: "@types/mime@npm:3.0.1" - checksum: 4040fac73fd0cea2460e29b348c1a6173da747f3a87da0dbce80dd7a9355a3d0e51d6d9a401654f3e5550620e3718b5a899b2ec1debf18424e298a2c605346e7 + version: 3.0.4 + resolution: "@types/mime@npm:3.0.4" + checksum: a6139c8e1f705ef2b064d072f6edc01f3c099023ad7c4fce2afc6c2bf0231888202adadbdb48643e8e20da0ce409481a49922e737eca52871b3dc08017455843 languageName: node linkType: hard "@types/mime@npm:^1": - version: 1.3.2 - resolution: "@types/mime@npm:1.3.2" - checksum: 0493368244cced1a69cb791b485a260a422e6fcc857782e1178d1e6f219f1b161793e9f87f5fae1b219af0f50bee24fcbe733a18b4be8fdd07a38a8fb91146fd + version: 1.3.5 + resolution: "@types/mime@npm:1.3.5" + checksum: e29a5f9c4776f5229d84e525b7cd7dd960b51c30a0fb9a028c0821790b82fca9f672dab56561e2acd9e8eed51d431bde52eafdfef30f643586c4162f1aecfc78 languageName: node linkType: hard "@types/minimist@npm:^1.2.2": - version: 1.2.2 - resolution: "@types/minimist@npm:1.2.2" - checksum: b8da83c66eb4aac0440e64674b19564d9d86c80ae273144db9681e5eeff66f238ade9515f5006ffbfa955ceff8b89ad2bd8ec577d7caee74ba101431fb07045d + version: 1.2.5 + resolution: "@types/minimist@npm:1.2.5" + checksum: 477047b606005058ab0263c4f58097136268007f320003c348794f74adedc3166ffc47c80ec3e94687787f2ab7f4e72c468223946e79892cf0fd9e25e9970a90 languageName: node linkType: hard "@types/mocha@npm:^10.0.1": - version: 10.0.1 - resolution: "@types/mocha@npm:10.0.1" - checksum: 224ea9fce7b1734ccdb9aa99a622d902a538ce1847bca7fd22c5fb38adcf3ed536f50f48f587085db988a4bb3c2eb68f4b98e1cd6a38bc5547bd3bbbedc54495 + version: 10.0.6 + resolution: "@types/mocha@npm:10.0.6" + checksum: f7c836cf6cf27dc0f5970d262591b56f2a3caeaec8cfdc612c12e1cfbb207f601f710ece207e935164d4e3343b93be5054d0db5544f31f453b3923775d82099f languageName: node linkType: hard @@ -4724,10 +5414,28 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^20.5.7, @types/node@npm:^20.6.2": - version: 20.6.3 - resolution: "@types/node@npm:20.6.3" - checksum: 444a6f1f41cfa8d3e20ce0108e6e43960fb2ae0e481f233bb1c14d6252aa63a92e021de561cd317d9fdb411688f871065f40175a1f18763282dee2613a08f8a3 +"@types/ms@npm:*": + version: 0.7.34 + resolution: "@types/ms@npm:0.7.34" + checksum: f38d36e7b6edecd9badc9cf50474159e9da5fa6965a75186cceaf883278611b9df6669dc3a3cc122b7938d317b68a9e3d573d316fcb35d1be47ec9e468c6bd8a + languageName: node + linkType: hard + +"@types/node-forge@npm:^1.3.0": + version: 1.3.10 + resolution: "@types/node-forge@npm:1.3.10" + dependencies: + "@types/node": "*" + checksum: 363af42c83956c7e2483a71e398a02101ef6a55b4d86386c276315ca98bad02d6050b99fdbe13debcd1bcda250086b4a5b5c15a6fb2953d32420d269865ca7f8 + languageName: node + linkType: hard + +"@types/node@npm:*, @types/node@npm:^20.6.2": + version: 20.10.4 + resolution: "@types/node@npm:20.10.4" + dependencies: + undici-types: ~5.26.4 + checksum: 054b296417e771ab524bea63cf3289559c6bdf290d45428f7cc68e9b00030ff7a0ece47b8c99a26b4f47a443919813bcf42beadff2f0bea7d8125fa541d92eb0 languageName: node linkType: hard @@ -4746,16 +5454,18 @@ __metadata: linkType: hard "@types/node@npm:^18.7.20": - version: 18.17.18 - resolution: "@types/node@npm:18.17.18" - checksum: 59cbd906363d37017fe9ba0c08c1446e440d4d977459609c5f90b8fb7eb41f273ce8af30c5a5b5d599d7de934c1b3702bc9fc27caf8d2270e5cdb659c5232991 + version: 18.19.3 + resolution: "@types/node@npm:18.19.3" + dependencies: + undici-types: ~5.26.4 + checksum: 58c4fa45a78fcec75c78182a4b266395905957633654eb0311c5f9c30ac15c179ea2287ab1af034e46c2db7bb0589ef0000ee64c1de8f568a0aad29eaadb100c languageName: node linkType: hard "@types/parse-json@npm:^4.0.0": - version: 4.0.0 - resolution: "@types/parse-json@npm:4.0.0" - checksum: fd6bce2b674b6efc3db4c7c3d336bd70c90838e8439de639b909ce22f3720d21344f52427f1d9e57b265fcb7f6c018699b99e5e0c208a1a4823014269a6bf35b + version: 4.0.2 + resolution: "@types/parse-json@npm:4.0.2" + checksum: 5bf62eec37c332ad10059252fc0dab7e7da730764869c980b0714777ad3d065e490627be9f40fc52f238ffa3ac4199b19de4127196910576c2fe34dd47c7a470 languageName: node linkType: hard @@ -4774,11 +5484,11 @@ __metadata: linkType: hard "@types/pbkdf2@npm:^3.0.0": - version: 3.1.0 - resolution: "@types/pbkdf2@npm:3.1.0" + version: 3.1.2 + resolution: "@types/pbkdf2@npm:3.1.2" dependencies: "@types/node": "*" - checksum: d15024b1957c21cf3b8887329d9bd8dfde754cf13a09d76ae25f1391cfc62bb8b8d7b760773c5dbaa748172fba8b3e0c3dbe962af6ccbd69b76df12a48dfba40 + checksum: bebe1e596cbbe5f7d2726a58859e61986c5a42459048e29cb7f2d4d764be6bbb0844572fd5d70ca8955a8a17e8b4ed80984fc4903e165d9efb8807a3fbb051aa languageName: node linkType: hard @@ -4791,42 +5501,49 @@ __metadata: languageName: node linkType: hard +"@types/prismjs@npm:^1.26.0": + version: 1.26.3 + resolution: "@types/prismjs@npm:1.26.3" + checksum: c627fa9d9f4277ce413bb8347944152cddfc892702e34ff4b099dc1cf3f00c09514d36349c23529b903b0e57f3b2e0dc91ee66e98af07fbbe1e3fe8346b23370 + languageName: node + linkType: hard + "@types/prop-types@npm:*": - version: 15.7.8 - resolution: "@types/prop-types@npm:15.7.8" - checksum: 61dfad79da8b1081c450bab83b77935df487ae1cdd4660ec7df6be8e74725c15fa45cf486ce057addc956ca4ae78300b97091e2a25061133d1b9a1440bc896ae + version: 15.7.11 + resolution: "@types/prop-types@npm:15.7.11" + checksum: 7519ff11d06fbf6b275029fe03fff9ec377b4cb6e864cac34d87d7146c7f5a7560fd164bdc1d2dbe00b60c43713631251af1fd3d34d46c69cd354602bc0c7c54 languageName: node linkType: hard "@types/ps-tree@npm:^1.1.2": - version: 1.1.2 - resolution: "@types/ps-tree@npm:1.1.2" - checksum: 575c3b2b83ea8935ab296ac9e17f6a2c1a5bb155f9e30663bb7a7c741a8ca4641f0df9748866230f1d6c3f87ed4ffa3fa91f1df444ef9979a3df31114534bf25 + version: 1.1.6 + resolution: "@types/ps-tree@npm:1.1.6" + checksum: bf5b7bb9bd11b8762a8302b93c335728ecb19c85a74c640a3888d476368a03733f11612b9a87b1ad9ea56f95720db23a824c78113b16024dc59264b7f9008df5 languageName: node linkType: hard "@types/qs@npm:*": - version: 6.9.8 - resolution: "@types/qs@npm:6.9.8" - checksum: c28e07d00d07970e5134c6eed184a0189b8a4649e28fdf36d9117fe671c067a44820890de6bdecef18217647a95e9c6aebdaaae69f5fe4b0bec9345db885f77e + version: 6.9.10 + resolution: "@types/qs@npm:6.9.10" + checksum: 3e479ee056bd2b60894baa119d12ecd33f20a25231b836af04654e784c886f28a356477630430152a86fba253da65d7ecd18acffbc2a8877a336e75aa0272c67 languageName: node linkType: hard "@types/range-parser@npm:*": - version: 1.2.4 - resolution: "@types/range-parser@npm:1.2.4" - checksum: b7c0dfd5080a989d6c8bb0b6750fc0933d9acabeb476da6fe71d8bdf1ab65e37c136169d84148034802f48378ab94e3c37bb4ef7656b2bec2cb9c0f8d4146a95 + version: 1.2.7 + resolution: "@types/range-parser@npm:1.2.7" + checksum: 95640233b689dfbd85b8c6ee268812a732cf36d5affead89e806fe30da9a430767af8ef2cd661024fd97e19d61f3dec75af2df5e80ec3bea000019ab7028629a languageName: node linkType: hard -"@types/react-router-config@npm:*, @types/react-router-config@npm:^5.0.6": - version: 5.0.8 - resolution: "@types/react-router-config@npm:5.0.8" +"@types/react-router-config@npm:*, @types/react-router-config@npm:^5.0.6, @types/react-router-config@npm:^5.0.7": + version: 5.0.11 + resolution: "@types/react-router-config@npm:5.0.11" dependencies: "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router": ^5.1.0 - checksum: afbd96e526fcdd19a3c8604912496a5a7ecfdcd848632a003ef8af69701ca74f14451e4fac93d265b678ca07c82ec4a103126f64c040a4aefa1a8172619be2bd + checksum: 4b72d9b71e0576e193c11e5085bbdac43f31debfa3b6ebc24666f3d646ef25c1f57f16c29b1ddd3051c881e85f8e0d4ab5a7bbd5fc215b9377f57675b210be7c languageName: node linkType: hard @@ -4852,13 +5569,13 @@ __metadata: linkType: hard "@types/react@npm:*": - version: 18.2.28 - resolution: "@types/react@npm:18.2.28" + version: 18.2.43 + resolution: "@types/react@npm:18.2.43" dependencies: "@types/prop-types": "*" "@types/scheduler": "*" csstype: ^3.0.2 - checksum: 81381bedeba83278f4c9febb0b83e0bd3f42a25897a50b9cb36ef53651d34b3d50f87ebf11211ea57ea575131f85d31e93e496ce46478a00b0f9bf7b26b5917a + checksum: e7e4da18c7b14e4b8b1ea630d1d8224835698f2bb2485766455bfb9dea93b8ee6cc549a9fe1cb10c984e62685db44fcfb61e8fac913b008cd30a92087f25b9df languageName: node linkType: hard @@ -4882,11 +5599,11 @@ __metadata: linkType: hard "@types/responselike@npm:^1.0.0": - version: 1.0.1 - resolution: "@types/responselike@npm:1.0.1" + version: 1.0.3 + resolution: "@types/responselike@npm:1.0.3" dependencies: "@types/node": "*" - checksum: ae8c36c9354aaedfa462dab655aa17613529d545a418acc54ba0214145fc1d0454be2ae107031a1b2c24768f19f2af7e4096a85d1e604010becd0bec2355cb0e + checksum: 6ac4b35723429b11b117e813c7acc42c3af8b5554caaf1fc750404c1ae59f9b7376bc69b9e9e194a5a97357a597c2228b7173d317320f0360d617b6425212f58 languageName: node linkType: hard @@ -4898,91 +5615,87 @@ __metadata: linkType: hard "@types/sax@npm:^1.2.1": - version: 1.2.5 - resolution: "@types/sax@npm:1.2.5" + version: 1.2.7 + resolution: "@types/sax@npm:1.2.7" dependencies: "@types/node": "*" - checksum: a4bf27d7eb1b99030e75dea01fab2fa3959554f5c463b4f577dbbc9d8ed88a5b26b83ac84d045ae5a53e350057f120574db6e1c4e8507c011299dd023e4fa4f2 + checksum: 7ece5fbb5d9c8fc76ab0de2f99d705edf92f18e701d4f9d9b0647275e32eb65e656c1badf9dfaa12f4e1ff3e250561c8c9cfe79e8b5f33dd1417ac0f1804f6cc languageName: node linkType: hard "@types/scheduler@npm:*": - version: 0.16.4 - resolution: "@types/scheduler@npm:0.16.4" - checksum: a57b0f10da1b021e6bd5eeef8a1917dd3b08a8715bd8029e2ded2096d8f091bb1bb1fef2d66e139588a983c4bfbad29b59e48011141725fa83c76e986e1257d7 + version: 0.16.8 + resolution: "@types/scheduler@npm:0.16.8" + checksum: 6c091b096daa490093bf30dd7947cd28e5b2cd612ec93448432b33f724b162587fed9309a0acc104d97b69b1d49a0f3fc755a62282054d62975d53d7fd13472d languageName: node linkType: hard "@types/secp256k1@npm:^4.0.1": - version: 4.0.4 - resolution: "@types/secp256k1@npm:4.0.4" + version: 4.0.6 + resolution: "@types/secp256k1@npm:4.0.6" dependencies: "@types/node": "*" - checksum: 6f521a08486a98e71c8529f5c3119f99e610196a47243cc6052c6160b216dff2c85dc50a8f3208ed47028dbb470bbb6fdee47a3fdc064687e46021d5a712767c + checksum: 984494caf49a4ce99fda2b9ea1840eb47af946b8c2737314108949bcc0c06b4880e871296bd49ed6ea4c8423e3a302ad79fec43abfc987330e7eb98f0c4e8ba4 languageName: node linkType: hard "@types/semver@npm:^7.5.0": - version: 7.5.3 - resolution: "@types/semver@npm:7.5.3" - checksum: 349fdd1ab6c213bac5c991bac766bd07b8b12e63762462bb058740dcd2eb09c8193d068bb226f134661275f2022976214c0e727a4e5eb83ec1b131127c980d3e + version: 7.5.6 + resolution: "@types/semver@npm:7.5.6" + checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 languageName: node linkType: hard "@types/send@npm:*": - version: 0.17.1 - resolution: "@types/send@npm:0.17.1" + version: 0.17.4 + resolution: "@types/send@npm:0.17.4" dependencies: "@types/mime": ^1 "@types/node": "*" - checksum: 10b620a5960058ef009afbc17686f680d6486277c62f640845381ec4baa0ea683fdd77c3afea4803daf5fcddd3fb2972c8aa32e078939f1d4e96f83195c89793 + checksum: cf4db48251bbb03cd6452b4de6e8e09e2d75390a92fd798eca4a803df06444adc94ed050246c94c7ed46fb97be1f63607f0e1f13c3ce83d71788b3e08640e5e0 languageName: node linkType: hard "@types/serve-index@npm:^1.9.1": - version: 1.9.2 - resolution: "@types/serve-index@npm:1.9.2" + version: 1.9.4 + resolution: "@types/serve-index@npm:1.9.4" dependencies: "@types/express": "*" - checksum: 4fd0a8fcdd6e2b2d7704a539b7c1e0d143e9e00be4c3992394fe2ef7e9b67283d74b43db3f92b0e0717d779aa51184168bbae617d30456357cb95ec58aa59ea8 + checksum: 72727c88d54da5b13275ebfb75dcdc4aa12417bbe9da1939e017c4c5f0c906fae843aa4e0fbfe360e7ee9df2f3d388c21abfc488f77ce58693fb57809f8ded92 languageName: node linkType: hard -"@types/serve-static@npm:*": - version: 1.15.2 - resolution: "@types/serve-static@npm:1.15.2" +"@types/serve-static@npm:*, @types/serve-static@npm:^1.13.10": + version: 1.15.5 + resolution: "@types/serve-static@npm:1.15.5" dependencies: "@types/http-errors": "*" "@types/mime": "*" "@types/node": "*" - checksum: 15c261dbfc57890f7cc17c04d5b22b418dfa0330c912b46c5d8ae2064da5d6f844ef7f41b63c7f4bbf07675e97ebe6ac804b032635ec742ae45d6f1274259b3e + checksum: 0ff4b3703cf20ba89c9f9e345bc38417860a88e85863c8d6fe274a543220ab7f5f647d307c60a71bb57dc9559f0890a661e8dc771a6ec5ef195d91c8afc4a893 languageName: node linkType: hard -"@types/serve-static@npm:^1.13.10": - version: 1.15.3 - resolution: "@types/serve-static@npm:1.15.3" +"@types/sockjs@npm:^0.3.33": + version: 0.3.36 + resolution: "@types/sockjs@npm:0.3.36" dependencies: - "@types/http-errors": "*" - "@types/mime": "*" "@types/node": "*" - checksum: afa52252f0ba94cdb5391e80f23e17fd629bdf2a31be8876e2c4490312ed6b0570822dd7de7cea04c9002049e207709563568b7f4ee10bb9f456321db1e83e40 + checksum: b4b5381122465d80ea8b158537c00bc82317222d3fb31fd7229ff25b31fa89134abfbab969118da55622236bf3d8fee75759f3959908b5688991f492008f29bc languageName: node linkType: hard -"@types/sockjs@npm:^0.3.33": - version: 0.3.34 - resolution: "@types/sockjs@npm:0.3.34" - dependencies: - "@types/node": "*" - checksum: 1d38b1976a97f5895a6be00cead1b2a59d842f023b6e35450b7eec8a3131c860c447aba3f7ea3c880c066d8277b0c76fae9d080be1aad475811b568ed6079d49 +"@types/unist@npm:*, @types/unist@npm:^3.0.0": + version: 3.0.2 + resolution: "@types/unist@npm:3.0.2" + checksum: 3d04d0be69316e5f14599a0d993a208606c12818cf631fd399243d1dc7a9bd8a3917d6066baa6abc290814afbd744621484756803c80cba892c39cd4b4a85616 languageName: node linkType: hard "@types/unist@npm:^2, @types/unist@npm:^2.0.0, @types/unist@npm:^2.0.2, @types/unist@npm:^2.0.3": - version: 2.0.8 - resolution: "@types/unist@npm:2.0.8" - checksum: f4852d10a6752dc70df363917ef74453e5d2fd42824c0f6d09d19d530618e1402193977b1207366af4415aaec81d4e262c64d00345402020c4ca179216e553c7 + version: 2.0.10 + resolution: "@types/unist@npm:2.0.10" + checksum: e2924e18dedf45f68a5c6ccd6015cd62f1643b1b43baac1854efa21ae9e70505db94290434a23da1137d9e31eb58e54ca175982005698ac37300a1c889f6c4aa languageName: node linkType: hard @@ -5003,48 +5716,48 @@ __metadata: linkType: hard "@types/ws@npm:^8.5.5": - version: 8.5.7 - resolution: "@types/ws@npm:8.5.7" + version: 8.5.10 + resolution: "@types/ws@npm:8.5.10" dependencies: "@types/node": "*" - checksum: 4502085c0f7ae6b36d5419c0fc6ce4b9002ee5e997a8708d6ed10b393e97091e1b986e8038ec604945c194f14aac150e74d6596629a2775628d122f552009c35 + checksum: 3ec416ea2be24042ebd677932a462cf16d2080393d8d7d0b1b3f5d6eaa4a7387aaf0eefb99193c0bfd29444857cf2e0c3ac89899e130550dc6c14ada8a46d25e languageName: node linkType: hard "@types/yargs-parser@npm:*": - version: 21.0.1 - resolution: "@types/yargs-parser@npm:21.0.1" - checksum: 64e6316c2045e2d460c4fb79572f872f9d2f98fddc6d9d3949c71f0b6ad0ef8a2706cf49db26dfb02a9cb81433abb8f340f015e1d20a9692279abe9477b72c8e + version: 21.0.3 + resolution: "@types/yargs-parser@npm:21.0.3" + checksum: ef236c27f9432983e91432d974243e6c4cdae227cb673740320eff32d04d853eed59c92ca6f1142a335cfdc0e17cccafa62e95886a8154ca8891cc2dec4ee6fc languageName: node linkType: hard "@types/yargs@npm:^17.0.8": - version: 17.0.28 - resolution: "@types/yargs@npm:17.0.28" + version: 17.0.32 + resolution: "@types/yargs@npm:17.0.32" dependencies: "@types/yargs-parser": "*" - checksum: f78c5e5c29903933c0557b4ffcd1d0b8564d66859c8ca4aa51da3714e49109ed7c2644334a1918d033df19028f4cecc91fd2e502651bb8e8451f246c371da847 + checksum: 4505bdebe8716ff383640c6e928f855b5d337cb3c68c81f7249fc6b983d0aa48de3eee26062b84f37e0d75a5797bc745e0c6e76f42f81771252a758c638f36ba languageName: node linkType: hard "@types/yauzl@npm:^2.9.1": - version: 2.10.0 - resolution: "@types/yauzl@npm:2.10.0" + version: 2.10.3 + resolution: "@types/yauzl@npm:2.10.3" dependencies: "@types/node": "*" - checksum: 55d27ae5d346ea260e40121675c24e112ef0247649073848e5d4e03182713ae4ec8142b98f61a1c6cbe7d3b72fa99bbadb65d8b01873e5e605cdc30f1ff70ef2 + checksum: 5ee966ea7bd6b2802f31ad4281c92c4c0b6dfa593c378a2582c58541fa113bec3d70eb0696b34ad95e8e6861a884cba6c3e351285816693ed176222f840a8c08 languageName: node linkType: hard "@typescript-eslint/eslint-plugin@npm:^6.7.3": - version: 6.7.3 - resolution: "@typescript-eslint/eslint-plugin@npm:6.7.3" + version: 6.13.2 + resolution: "@typescript-eslint/eslint-plugin@npm:6.13.2" dependencies: "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 6.7.3 - "@typescript-eslint/type-utils": 6.7.3 - "@typescript-eslint/utils": 6.7.3 - "@typescript-eslint/visitor-keys": 6.7.3 + "@typescript-eslint/scope-manager": 6.13.2 + "@typescript-eslint/type-utils": 6.13.2 + "@typescript-eslint/utils": 6.13.2 + "@typescript-eslint/visitor-keys": 6.13.2 debug: ^4.3.4 graphemer: ^1.4.0 ignore: ^5.2.4 @@ -5057,44 +5770,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: ac2790882199047abc59c0407a862f3339645623d03ea0aae5a73fd4bac6abfb753afcf9f23fd51cd1d5aa73f132ef94e2850774c4b2a3d99ebb83030b09429c + checksum: e50cbbe7104eecef59faf3355ab981d9f353b19327f0b4607dfd829b4726f9e694b536fe43ab55f50bb00fbfdd2e4268a7e2a568b28d5fcd0d2a32a8d2466218 languageName: node linkType: hard "@typescript-eslint/parser@npm:^6.7.3": - version: 6.7.3 - resolution: "@typescript-eslint/parser@npm:6.7.3" + version: 6.13.2 + resolution: "@typescript-eslint/parser@npm:6.13.2" dependencies: - "@typescript-eslint/scope-manager": 6.7.3 - "@typescript-eslint/types": 6.7.3 - "@typescript-eslint/typescript-estree": 6.7.3 - "@typescript-eslint/visitor-keys": 6.7.3 + "@typescript-eslint/scope-manager": 6.13.2 + "@typescript-eslint/types": 6.13.2 + "@typescript-eslint/typescript-estree": 6.13.2 + "@typescript-eslint/visitor-keys": 6.13.2 debug: ^4.3.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 658f3294b281db06ebb46884b92172d45eb402ec25c7d4a09cc2461eee359266029af7a49eb9006ee7c3e0003ba53a06f4bee84aa2e99d2d9a3507b9c84ff775 + checksum: aeafc414d295d7855384f10d57abb4f5f2ff35b57991b5c8854f43268761b3cc995e62af585dea1dc48295d762f466b565b5ae5699bfe642585d3f83ba8e1515 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.7.3": - version: 6.7.3 - resolution: "@typescript-eslint/scope-manager@npm:6.7.3" +"@typescript-eslint/scope-manager@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/scope-manager@npm:6.13.2" dependencies: - "@typescript-eslint/types": 6.7.3 - "@typescript-eslint/visitor-keys": 6.7.3 - checksum: 08215444b7c70af5c45e185ba3c31c550a0a671ab464a67058cbee680c94aa9d1a062958976d8b09f7bcabf2f63114cdc7be2e4e32e2dfdcb2d7cc79961b7b32 + "@typescript-eslint/types": 6.13.2 + "@typescript-eslint/visitor-keys": 6.13.2 + checksum: ff8fd64ddf324e296e2e0e34a8f73149c9a5f14d1761ea8e8665fc5998faa2b0bbbd1a5d416aa10d725f13c804032d532f68e39a0ca6cc36d1c9b9c0aea94311 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.7.3": - version: 6.7.3 - resolution: "@typescript-eslint/type-utils@npm:6.7.3" +"@typescript-eslint/type-utils@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/type-utils@npm:6.13.2" dependencies: - "@typescript-eslint/typescript-estree": 6.7.3 - "@typescript-eslint/utils": 6.7.3 + "@typescript-eslint/typescript-estree": 6.13.2 + "@typescript-eslint/utils": 6.13.2 debug: ^4.3.4 ts-api-utils: ^1.0.1 peerDependencies: @@ -5102,23 +5815,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: f30a5ab4f88f76457810d72e3ada79fefd94dbbb456069ac004bd7601c9b7f15689b906b66cd849c230f30ae65f6f7039fb169609177ab545b34bacab64f015e + checksum: ba54e5746139f778c35e4058e523ec8c20b68cf6472b3a7784170328e48c228f0761d2fc7e43dab053ca7d85ac4378b6965567774e6afedf551e600638404215 languageName: node linkType: hard -"@typescript-eslint/types@npm:6.7.3": - version: 6.7.3 - resolution: "@typescript-eslint/types@npm:6.7.3" - checksum: 4adb6177ec710e7438610fee553839a7abecc498dbb36d0170786bab66c5e5415cd720ac06419fd905458ad88c39b661603af5f013adc299137ccb4c51c4c879 +"@typescript-eslint/types@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/types@npm:6.13.2" + checksum: 4493ff06fa07c68c5adbcbd842f6dd6f5c88f14d160b53c3379b6b703e6f62808fab7fdebcc06ff06a56f20ab432b6ceeb0afb8931dc97d4061cb417e787f2c1 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.7.3": - version: 6.7.3 - resolution: "@typescript-eslint/typescript-estree@npm:6.7.3" +"@typescript-eslint/typescript-estree@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/typescript-estree@npm:6.13.2" dependencies: - "@typescript-eslint/types": 6.7.3 - "@typescript-eslint/visitor-keys": 6.7.3 + "@typescript-eslint/types": 6.13.2 + "@typescript-eslint/visitor-keys": 6.13.2 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -5127,34 +5840,41 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: eaba1feb0e6882b0bad292172c118aac43ba683d1f04b940b542a20035468d030b062b036ea49eca36aa21782e9b1019e87717003b3c3db7d12dc707466b7eb7 + checksum: 0c18ee5ef594a2411a788fe9d7bc6d51a03bce38d9d764bcb24ab557e5bc1942c2ddf9bd6fb4877eb102b0ae488974fb7b7fe72daa70a2054bf04d3cc6803546 languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.7.3": - version: 6.7.3 - resolution: "@typescript-eslint/utils@npm:6.7.3" +"@typescript-eslint/utils@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/utils@npm:6.13.2" dependencies: "@eslint-community/eslint-utils": ^4.4.0 "@types/json-schema": ^7.0.12 "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 6.7.3 - "@typescript-eslint/types": 6.7.3 - "@typescript-eslint/typescript-estree": 6.7.3 + "@typescript-eslint/scope-manager": 6.13.2 + "@typescript-eslint/types": 6.13.2 + "@typescript-eslint/typescript-estree": 6.13.2 semver: ^7.5.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 685b7c9fa95ad085f30e26431dc41b3059a42a16925defe2a94b32fb46974bfc168000de7d4d9ad4a1d0568a983f9d3c01ea6bc6cfa9a798e482719af9e9165b + checksum: b66bcf2a945e9c55f3dccb48af49565863d974837ee23b2f01ce7f3fb2462eb8a5871784d4a2fcc80dac7d5cd4ed90c8d01431cd177c0249de89a448f6663fc8 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.7.3": - version: 6.7.3 - resolution: "@typescript-eslint/visitor-keys@npm:6.7.3" +"@typescript-eslint/visitor-keys@npm:6.13.2": + version: 6.13.2 + resolution: "@typescript-eslint/visitor-keys@npm:6.13.2" dependencies: - "@typescript-eslint/types": 6.7.3 + "@typescript-eslint/types": 6.13.2 eslint-visitor-keys: ^3.4.1 - checksum: cef64173a919107f420703e204d97d0afef0d9bd7a67570df5bdb39ac9464211c5a7b3af735d8f41e8004b443ab83e88b1d6fb951886aed4d3fe9d4778667199 + checksum: 4b4def7acd7451e6a18dab3ee13f06504b3d23e51f195fced7c544f2203ee8a83426c82fa57ab6b58725c70fdedaf7a3eccb69793180be35756eed0f2c69fe04 + languageName: node + linkType: hard + +"@ungap/structured-clone@npm:^1.0.0, @ungap/structured-clone@npm:^1.2.0": + version: 1.2.0 + resolution: "@ungap/structured-clone@npm:1.2.0" + checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524 languageName: node linkType: hard @@ -5167,12 +5887,12 @@ __metadata: languageName: node linkType: hard -"@web/browser-logs@npm:^0.3.2": - version: 0.3.3 - resolution: "@web/browser-logs@npm:0.3.3" +"@web/browser-logs@npm:^0.3.4": + version: 0.3.4 + resolution: "@web/browser-logs@npm:0.3.4" dependencies: errorstacks: ^2.2.0 - checksum: 08db1332f7151e8e0fb1ed61e6e10f736e44f5c9675423f3af0c24f3a764560ea115e956cf3a4d9cd7a0826c0126accf966ebdb0bfa25a72c7e79da47b2cee3b + checksum: fe212c91c26deada3458b6562a8d7d2ae98b7b51c7099e1cdb972e9f799c63f6cd170776b2eadbe43c47531cb6d9b06f48282113a5944f4394270a0076f8565e languageName: node linkType: hard @@ -5211,13 +5931,13 @@ __metadata: languageName: node linkType: hard -"@web/dev-server-core@npm:^0.5.1": - version: 0.5.2 - resolution: "@web/dev-server-core@npm:0.5.2" +"@web/dev-server-core@npm:^0.6.2": + version: 0.6.3 + resolution: "@web/dev-server-core@npm:0.6.3" dependencies: "@types/koa": ^2.11.6 "@types/ws": ^7.4.0 - "@web/parse5-utils": ^2.0.0 + "@web/parse5-utils": ^2.0.2 chokidar: ^3.4.3 clone: ^2.1.2 es-module-lexer: ^1.0.0 @@ -5233,7 +5953,7 @@ __metadata: parse5: ^6.0.1 picomatch: ^2.2.2 ws: ^7.4.2 - checksum: 1a42f71a3d7eafd41bdb33a8cf9d37bb7e205704f3bcde9e32bd0aa639759d7a6e4448efe448be127042c46816931dd7585575e0f30a15c1b22576d578ccaacc + checksum: 98ba42df5eb865828c223bd1de098d013efd8e89983efff28e26ecd9d08c8b35fd29b4c1256ed08b05ecb365abe1aa80d2854e1953bdebbbe230a7e2a597dd8f languageName: node linkType: hard @@ -5299,13 +6019,13 @@ __metadata: languageName: node linkType: hard -"@web/parse5-utils@npm:^2.0.0": - version: 2.0.1 - resolution: "@web/parse5-utils@npm:2.0.1" +"@web/parse5-utils@npm:^2.0.2": + version: 2.1.0 + resolution: "@web/parse5-utils@npm:2.1.0" dependencies: "@types/parse5": ^6.0.1 parse5: ^6.0.1 - checksum: d3993b0dee350e040bf5b13749283df88c97a48b063f8938fb21623422cd5f03b641393ca03bc724936e9f17d8bfd7939f501de6eb1c33ad82f6ac5112bf6cff + checksum: 0faa93c51d61934e0006bebc2e257036f8cedeb455c7bf22b8fdbc17919929518c2cc99ced3769f8eb3b1d6694dd4a7186d66ad2b3c4330140fd2ce03dc6c4d2 languageName: node linkType: hard @@ -5365,9 +6085,9 @@ __metadata: languageName: node linkType: hard -"@web/test-runner-core@npm:^0.11.0": - version: 0.11.4 - resolution: "@web/test-runner-core@npm:0.11.4" +"@web/test-runner-core@npm:^0.12.0": + version: 0.12.0 + resolution: "@web/test-runner-core@npm:0.12.0" dependencies: "@babel/code-frame": ^7.12.11 "@types/babel__code-frame": ^7.0.2 @@ -5376,8 +6096,8 @@ __metadata: "@types/debounce": ^1.2.0 "@types/istanbul-lib-coverage": ^2.0.3 "@types/istanbul-reports": ^3.0.0 - "@web/browser-logs": ^0.3.2 - "@web/dev-server-core": ^0.5.1 + "@web/browser-logs": ^0.3.4 + "@web/dev-server-core": ^0.6.2 chokidar: ^3.4.3 cli-cursor: ^3.1.0 co-body: ^6.1.0 @@ -5395,7 +6115,7 @@ __metadata: open: ^8.0.2 picomatch: ^2.2.2 source-map: ^0.7.3 - checksum: 45aea23ae1b0d112e2d331c15e1e581b5d208c278e6ecab746cffba81d0d11a8fd7b3fb0da488dd3c3c01e49debf7f3e8261031c2b86a7c8716fb3cc3e1a172c + checksum: e71afa227f9dc2ea4ec67838b1bc4c8af2c61d3e6002b78e37724e3dc09be466e7f7aa5e6795d5431dca1a0b13b94765a880103f98c5497c97943c2f708327eb languageName: node linkType: hard @@ -5411,16 +6131,16 @@ __metadata: languageName: node linkType: hard -"@web/test-runner-coverage-v8@npm:^0.7.0": - version: 0.7.1 - resolution: "@web/test-runner-coverage-v8@npm:0.7.1" +"@web/test-runner-coverage-v8@npm:^0.7.3": + version: 0.7.3 + resolution: "@web/test-runner-coverage-v8@npm:0.7.3" dependencies: - "@web/test-runner-core": ^0.11.0 + "@web/test-runner-core": ^0.12.0 istanbul-lib-coverage: ^3.0.0 lru-cache: ^8.0.4 picomatch: ^2.2.2 v8-to-istanbul: ^9.0.1 - checksum: 317b11502b1378097598458a54054353fdb94d3bf9e0954daa9a3b1dcc1f0664032cd18f48292e763b890a132a980f5a5ead6555c33e9fb064d0ca960a884292 + checksum: 05d7a9a4df8ca30991307a8d69ac9388a6572a9c6585887a925e7bdb158a0430f213c81cb356b8dcb7bf9cd3423d0071030b481c29358562bd344da8ea814daa languageName: node linkType: hard @@ -5435,13 +6155,13 @@ __metadata: linkType: hard "@web/test-runner-playwright@npm:^0.10.0": - version: 0.10.1 - resolution: "@web/test-runner-playwright@npm:0.10.1" + version: 0.10.3 + resolution: "@web/test-runner-playwright@npm:0.10.3" dependencies: - "@web/test-runner-core": ^0.11.0 - "@web/test-runner-coverage-v8": ^0.7.0 + "@web/test-runner-core": ^0.12.0 + "@web/test-runner-coverage-v8": ^0.7.3 playwright: ^1.22.2 - checksum: d2aebc54c0444fb434671dc0d3a3912f76570eae4a909b7912cf46b9535232c7f7829729554e8629f546abce48433f9f5b21d583011582753fbb40e288c28e80 + checksum: 7c765d34482f2e299742c3ffe80790229d0825569016ccfccbb1a0c915f89551a3cc14a1454ed7c6895aaa03605ea444f7c1846eeab82bf02702e87a60628b3c languageName: node linkType: hard @@ -5637,10 +6357,17 @@ __metadata: languageName: node linkType: hard -"abbrev@npm:^1.0.0": - version: 1.1.1 - resolution: "abbrev@npm:1.1.1" - checksum: a4a97ec07d7ea112c517036882b2ac22f3109b7b19077dc656316d07d308438aac28e4d9746dc4d84bf6b1e75b4a7b0a5f3cb30592419f128ca9a8cee3bcfa17 +"@zeit/schemas@npm:2.29.0": + version: 2.29.0 + resolution: "@zeit/schemas@npm:2.29.0" + checksum: 3cea06bb67d790336aca0cc17580fd492ff3fc66ef4d180dce7053ff7ff54ab81b56bf718ba6f537148c581161d06306a481ec218d540bff922e0e009844ffd1 + languageName: node + linkType: hard + +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: 0e994ad2aa6575f94670d8a2149afe94465de9cedaaaac364e7fb43a40c3691c980ff74899f682f4ca58fa96b4cbd7421a015d3a6defe43a442117d7821a2f36 languageName: node linkType: hard @@ -5678,7 +6405,7 @@ __metadata: languageName: node linkType: hard -"acorn-jsx@npm:^5.3.2": +"acorn-jsx@npm:^5.0.0, acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" peerDependencies: @@ -5687,19 +6414,19 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.0.0, acorn-walk@npm:^8.1.1, acorn-walk@npm:^8.2.0": - version: 8.2.0 - resolution: "acorn-walk@npm:8.2.0" - checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 +"acorn-walk@npm:^8.0.0, acorn-walk@npm:^8.1.1": + version: 8.3.1 + resolution: "acorn-walk@npm:8.3.1" + checksum: 5c8926ddb5400bc825b6baca782931f9df4ace603ba1a517f5243290fd9cdb089d52877840687b5d5c939591ebc314e2e63721514feaa37c6829c828f2b940ce languageName: node linkType: hard -"acorn@npm:^8.0.4, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": - version: 8.10.0 - resolution: "acorn@npm:8.10.0" +"acorn@npm:^8.0.0, acorn@npm:^8.0.4, acorn@npm:^8.4.1, acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": + version: 8.11.2 + resolution: "acorn@npm:8.11.2" bin: acorn: bin/acorn - checksum: 538ba38af0cc9e5ef983aee196c4b8b4d87c0c94532334fa7e065b2c8a1f85863467bb774231aae91613fcda5e68740c15d97b1967ae3394d20faddddd8af61d + checksum: 818450408684da89423e3daae24e4dc9b68692db8ab49ea4569c7c5abb7a3f23669438bf129cc81dfdada95e1c9b944ee1bfca2c57a05a4dc73834a612fbf6a7 languageName: node linkType: hard @@ -5731,7 +6458,7 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:6, agent-base@npm:^6.0.2": +"agent-base@npm:6": version: 6.0.2 resolution: "agent-base@npm:6.0.2" dependencies: @@ -5740,12 +6467,12 @@ __metadata: languageName: node linkType: hard -"agentkeepalive@npm:^4.2.1": - version: 4.5.0 - resolution: "agentkeepalive@npm:4.5.0" +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": + version: 7.1.0 + resolution: "agent-base@npm:7.1.0" dependencies: - humanize-ms: ^1.2.1 - checksum: 13278cd5b125e51eddd5079f04d6fe0914ac1b8b91c1f3db2c1822f99ac1a7457869068997784342fe455d59daaff22e14fb7b8c3da4e741896e7e31faf92481 + debug: ^4.3.4 + checksum: f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f languageName: node linkType: hard @@ -5759,16 +6486,6 @@ __metadata: languageName: node linkType: hard -"aggregate-error@npm:^4.0.0": - version: 4.0.1 - resolution: "aggregate-error@npm:4.0.1" - dependencies: - clean-stack: ^4.0.0 - indent-string: ^5.0.0 - checksum: bb3ffdfd13447800fff237c2cba752c59868ee669104bb995dfbbe0b8320e967d679e683dabb640feb32e4882d60258165cde0baafc4cd467cc7d275a13ad6b5 - languageName: node - linkType: hard - "ajv-formats@npm:^2.1.1": version: 2.1.1 resolution: "ajv-formats@npm:2.1.1" @@ -5803,6 +6520,18 @@ __metadata: languageName: node linkType: hard +"ajv@npm:8.11.0": + version: 8.11.0 + resolution: "ajv@npm:8.11.0" + dependencies: + fast-deep-equal: ^3.1.1 + json-schema-traverse: ^1.0.0 + require-from-string: ^2.0.2 + uri-js: ^4.2.2 + checksum: 5e0ff226806763be73e93dd7805b634f6f5921e3e90ca04acdf8db81eed9d8d3f0d4c5f1213047f45ebbf8047ffe0c840fa1ef2ec42c3a644899f69aa72b5bef + languageName: node + linkType: hard + "ajv@npm:^6.12.2, ajv@npm:^6.12.4, ajv@npm:^6.12.5": version: 6.12.6 resolution: "ajv@npm:6.12.6" @@ -5827,18 +6556,18 @@ __metadata: languageName: node linkType: hard -"algoliasearch-helper@npm:^3.10.0": - version: 3.14.2 - resolution: "algoliasearch-helper@npm:3.14.2" +"algoliasearch-helper@npm:^3.13.3": + version: 3.16.0 + resolution: "algoliasearch-helper@npm:3.16.0" dependencies: "@algolia/events": ^4.0.1 peerDependencies: algoliasearch: ">= 3.1 < 6" - checksum: d66444b25fe8ee64675bb660ff1980870751818cb4a29c57bda6ca410372f2bfa031a455dcd5981941736db89d8294187c5b3bc1ce2a2567c6e43657ccd208b8 + checksum: e024ad33c65d1eb7a31290bcf0bec37f2485154364e90ada45e07242ac35155313fe913fabd08cdb4d69e2794cc7d09dda03878566cea286cfac8fd4cc61f33f languageName: node linkType: hard -"algoliasearch@npm:^4.13.1, algoliasearch@npm:^4.19.1": +"algoliasearch@npm:^4.18.0, algoliasearch@npm:^4.19.1": version: 4.20.0 resolution: "algoliasearch@npm:4.20.0" dependencies: @@ -5940,7 +6669,7 @@ __metadata: languageName: node linkType: hard -"ansi-styles@npm:^6.0.0, ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1": +"ansi-styles@npm:^6.1.0": version: 6.2.1 resolution: "ansi-styles@npm:6.2.1" checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 @@ -5957,20 +6686,17 @@ __metadata: languageName: node linkType: hard -"aproba@npm:^1.0.3 || ^2.0.0": - version: 2.0.0 - resolution: "aproba@npm:2.0.0" - checksum: 5615cadcfb45289eea63f8afd064ab656006361020e1735112e346593856f87435e02d8dcc7ff0d11928bc7d425f27bc7c2a84f6c0b35ab0ff659c814c138a24 +"arch@npm:^2.2.0": + version: 2.2.0 + resolution: "arch@npm:2.2.0" + checksum: e21b7635029fe8e9cdd5a026f9a6c659103e63fff423834323cdf836a1bb240a72d0c39ca8c470f84643385cf581bd8eda2cad8bf493e27e54bd9783abe9101f languageName: node linkType: hard -"are-we-there-yet@npm:^3.0.0": - version: 3.0.1 - resolution: "are-we-there-yet@npm:3.0.1" - dependencies: - delegates: ^1.0.0 - readable-stream: ^3.6.0 - checksum: 52590c24860fa7173bedeb69a4c05fb573473e860197f618b9a28432ee4379049336727ae3a1f9c4cb083114601c1140cee578376164d0e651217a9843f9fe83 +"arg@npm:5.0.2, arg@npm:^5.0.0": + version: 5.0.2 + resolution: "arg@npm:5.0.2" + checksum: 6c69ada1a9943d332d9e5382393e897c500908d91d5cb735a01120d5f71daf1b339b7b8980cbeaba8fd1afc68e658a739746179e4315a26e8a28951ff9930078 languageName: node linkType: hard @@ -5981,13 +6707,6 @@ __metadata: languageName: node linkType: hard -"arg@npm:^5.0.0": - version: 5.0.2 - resolution: "arg@npm:5.0.2" - checksum: 6c69ada1a9943d332d9e5382393e897c500908d91d5cb735a01120d5f71daf1b339b7b8980cbeaba8fd1afc68e658a739746179e4315a26e8a28951ff9930078 - languageName: node - linkType: hard - "argparse@npm:^1.0.7": version: 1.0.10 resolution: "argparse@npm:1.0.10" @@ -6025,13 +6744,6 @@ __metadata: languageName: node linkType: hard -"array-find-index@npm:^1.0.1": - version: 1.0.2 - resolution: "array-find-index@npm:1.0.2" - checksum: aac128bf369e1ac6c06ff0bb330788371c0e256f71279fb92d745e26fb4b9db8920e485b4ec25e841c93146bf71a34dcdbcefa115e7e0f96927a214d237b7081 - languageName: node - linkType: hard - "array-flatten@npm:1.1.1": version: 1.1.1 resolution: "array-flatten@npm:1.1.1" @@ -6053,27 +6765,6 @@ __metadata: languageName: node linkType: hard -"arrgv@npm:^1.0.2": - version: 1.0.2 - resolution: "arrgv@npm:1.0.2" - checksum: 470bbb406ea3b34810dd8b03c0b33282617a42d9fce0ab45d58596efefd042fc548eda49161fa8e3f607cbe9df90e7a67003a09043ab9081eff70f97c63dd0e2 - languageName: node - linkType: hard - -"arrify@npm:^3.0.0": - version: 3.0.0 - resolution: "arrify@npm:3.0.0" - checksum: d6c6f3dad9571234f320e130d57fddb2cc283c87f2ac7df6c7005dffc5161b7bb9376f4be655ed257050330336e84afc4f3020d77696ad231ff580a94ae5aba6 - languageName: node - linkType: hard - -"asap@npm:~2.0.3": - version: 2.0.6 - resolution: "asap@npm:2.0.6" - checksum: b296c92c4b969e973260e47523207cd5769abd27c245a68c26dc7a0fe8053c55bb04360237cb51cab1df52be939da77150ace99ad331fb7fb13b3423ed73ff3d - languageName: node - linkType: hard - "assertion-error@npm:^1.1.0": version: 1.1.0 resolution: "assertion-error@npm:1.1.0" @@ -6088,6 +6779,15 @@ __metadata: languageName: node linkType: hard +"astring@npm:^1.8.0": + version: 1.8.6 + resolution: "astring@npm:1.8.6" + bin: + astring: bin/astring + checksum: 6f034d2acef1dac8bb231e7cc26c573d3c14e1975ea6e04f20312b43d4f462f963209bc64187d25d477a182dc3c33277959a0156ab7a3617aa79b1eac4d88e1f + languageName: node + linkType: hard + "async@npm:^2.6.4": version: 2.6.4 resolution: "async@npm:2.6.4" @@ -6111,7 +6811,7 @@ __metadata: languageName: node linkType: hard -"autoprefixer@npm:^10.4.12, autoprefixer@npm:^10.4.7": +"autoprefixer@npm:^10.4.12, autoprefixer@npm:^10.4.14, autoprefixer@npm:^10.4.7": version: 10.4.16 resolution: "autoprefixer@npm:10.4.16" dependencies: @@ -6129,67 +6829,9 @@ __metadata: languageName: node linkType: hard -"ava@npm:^5.2.0": - version: 5.3.1 - resolution: "ava@npm:5.3.1" - dependencies: - acorn: ^8.8.2 - acorn-walk: ^8.2.0 - ansi-styles: ^6.2.1 - arrgv: ^1.0.2 - arrify: ^3.0.0 - callsites: ^4.0.0 - cbor: ^8.1.0 - chalk: ^5.2.0 - chokidar: ^3.5.3 - chunkd: ^2.0.1 - ci-info: ^3.8.0 - ci-parallel-vars: ^1.0.1 - clean-yaml-object: ^0.1.0 - cli-truncate: ^3.1.0 - code-excerpt: ^4.0.0 - common-path-prefix: ^3.0.0 - concordance: ^5.0.4 - currently-unhandled: ^0.4.1 - debug: ^4.3.4 - emittery: ^1.0.1 - figures: ^5.0.0 - globby: ^13.1.4 - ignore-by-default: ^2.1.0 - indent-string: ^5.0.0 - is-error: ^2.2.2 - is-plain-object: ^5.0.0 - is-promise: ^4.0.0 - matcher: ^5.0.0 - mem: ^9.0.2 - ms: ^2.1.3 - p-event: ^5.0.1 - p-map: ^5.5.0 - picomatch: ^2.3.1 - pkg-conf: ^4.0.0 - plur: ^5.1.0 - pretty-ms: ^8.0.0 - resolve-cwd: ^3.0.0 - stack-utils: ^2.0.6 - strip-ansi: ^7.0.1 - supertap: ^3.0.1 - temp-dir: ^3.0.0 - write-file-atomic: ^5.0.1 - yargs: ^17.7.2 - peerDependencies: - "@ava/typescript": "*" - peerDependenciesMeta: - "@ava/typescript": - optional: true - bin: - ava: entrypoints/cli.mjs - checksum: 126a5932baef74eccd8bec992bd522e25c05b6ee4985dde87c20cece76c2377f0bf9448f242f3f9cd2abbf7a5ac932fe4e4abde2a23792d6271a6088e5a1984e - languageName: node - linkType: hard - -"axios@npm:^0.25.0": - version: 0.25.0 - resolution: "axios@npm:0.25.0" +"axios@npm:^0.25.0": + version: 0.25.0 + resolution: "axios@npm:0.25.0" dependencies: follow-redirects: ^1.14.7 checksum: 2a8a3787c05f2a0c9c3878f49782357e2a9f38945b93018fb0c4fd788171c43dceefbb577988628e09fea53952744d1ecebde234b561f1e703aa43e0a598a3ad @@ -6197,13 +6839,13 @@ __metadata: linkType: hard "axios@npm:^1.4.0": - version: 1.5.1 - resolution: "axios@npm:1.5.1" + version: 1.6.2 + resolution: "axios@npm:1.6.2" dependencies: follow-redirects: ^1.15.0 form-data: ^4.0.0 proxy-from-env: ^1.1.0 - checksum: 4444f06601f4ede154183767863d2b8e472b4a6bfc5253597ed6d21899887e1fd0ee2b3de792ac4f8459fe2e359d2aa07c216e45fd8b9e4e0688a6ebf48a5a8d + checksum: 4a7429e2b784be0f2902ca2680964391eae7236faa3967715f30ea45464b98ae3f1c6f631303b13dfe721b17126b01f486c7644b9ef276bfc63112db9fd379f8 languageName: node linkType: hard @@ -6222,6 +6864,19 @@ __metadata: languageName: node linkType: hard +"babel-loader@npm:^9.1.3": + version: 9.1.3 + resolution: "babel-loader@npm:9.1.3" + dependencies: + find-cache-dir: ^4.0.0 + schema-utils: ^4.0.0 + peerDependencies: + "@babel/core": ^7.12.0 + webpack: ">=5" + checksum: b168dde5b8cf11206513371a79f86bb3faa7c714e6ec9fffd420876b61f3d7f5f4b976431095ef6a14bc4d324505126deb91045fd41e312ba49f4deaa166fe28 + languageName: node + linkType: hard + "babel-plugin-apply-mdx-type-prop@npm:1.6.22": version: 1.6.22 resolution: "babel-plugin-apply-mdx-type-prop@npm:1.6.22" @@ -6266,14 +6921,14 @@ __metadata: linkType: hard "babel-plugin-polyfill-corejs3@npm:^0.8.5": - version: 0.8.5 - resolution: "babel-plugin-polyfill-corejs3@npm:0.8.5" + version: 0.8.6 + resolution: "babel-plugin-polyfill-corejs3@npm:0.8.6" dependencies: "@babel/helper-define-polyfill-provider": ^0.4.3 - core-js-compat: ^3.32.2 + core-js-compat: ^3.33.1 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 54ff3956c4f88e483d38b27ceec6199b9e73fceac10ebf969469d215e6a62929384e4433f85335c9a6ba809329636e27f9bdae2f54075f833e7a745341c07d84 + checksum: 36951c2edac42ac0f05b200502e90d77bf66ccee5b52e2937d23496c6ef2372cce31b8c64144da374b77bd3eb65e2721703a52eac56cad16a152326c092cbf77 languageName: node linkType: hard @@ -6295,6 +6950,13 @@ __metadata: languageName: node linkType: hard +"bail@npm:^2.0.0": + version: 2.0.2 + resolution: "bail@npm:2.0.2" + checksum: aab4e8ccdc8d762bf3fdfce8e706601695620c0c2eda256dd85088dc0be3cfd7ff126f6e99c2bee1f24f5d418414aacf09d7f9702f16d6963df2fa488cda8824 + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -6311,13 +6973,6 @@ __metadata: languageName: node linkType: hard -"base16@npm:^1.0.0": - version: 1.0.0 - resolution: "base16@npm:1.0.0" - checksum: 0cd449a2db0f0f957e4b6b57e33bc43c9e20d4f1dd744065db94b5da35e8e71fa4dc4bc7a901e59a84d5f8b6936e3c520e2471787f667fc155fb0f50d8540f5d - languageName: node - linkType: hard - "base64-js@npm:^1.3.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" @@ -6340,9 +6995,9 @@ __metadata: linkType: hard "big-integer@npm:^1.6.44": - version: 1.6.51 - resolution: "big-integer@npm:1.6.51" - checksum: 3d444173d1b2e20747e2c175568bedeebd8315b0637ea95d75fd27830d3b8e8ba36c6af40374f36bdaea7b5de376dcada1b07587cb2a79a928fccdb6e6e3c518 + version: 1.6.52 + resolution: "big-integer@npm:1.6.52" + checksum: 6e86885787a20fed96521958ae9086960e4e4b5e74d04f3ef7513d4d0ad631a9f3bde2730fc8aaa4b00419fc865f6ec573e5320234531ef37505da7da192c40b languageName: node linkType: hard @@ -6385,13 +7040,6 @@ __metadata: languageName: node linkType: hard -"blueimp-md5@npm:^2.10.0": - version: 2.19.0 - resolution: "blueimp-md5@npm:2.19.0" - checksum: 28095dcbd2c67152a2938006e8d7c74c3406ba6556071298f872505432feb2c13241b0476644160ee0a5220383ba94cb8ccdac0053b51f68d168728f9c382530 - languageName: node - linkType: hard - "bn.js@npm:^4.11.0, bn.js@npm:^4.11.8, bn.js@npm:^4.11.9": version: 4.12.0 resolution: "bn.js@npm:4.12.0" @@ -6445,6 +7093,22 @@ __metadata: languageName: node linkType: hard +"boxen@npm:7.0.0": + version: 7.0.0 + resolution: "boxen@npm:7.0.0" + dependencies: + ansi-align: ^3.0.1 + camelcase: ^7.0.0 + chalk: ^5.0.1 + cli-boxes: ^3.0.0 + string-width: ^5.1.2 + type-fest: ^2.13.0 + widest-line: ^4.0.1 + wrap-ansi: ^8.0.1 + checksum: b917cf7a168ef3149635a8c02d5c9717d66182348bd27038d85328ad12655151e3324db0f2815253846c33e5f0ddf28b6cd52d56a12b9f88617b7f8f722b946a + languageName: node + linkType: hard + "boxen@npm:^5.0.0": version: 5.1.2 resolution: "boxen@npm:5.1.2" @@ -6477,6 +7141,22 @@ __metadata: languageName: node linkType: hard +"boxen@npm:^7.0.0": + version: 7.1.1 + resolution: "boxen@npm:7.1.1" + dependencies: + ansi-align: ^3.0.1 + camelcase: ^7.0.1 + chalk: ^5.2.0 + cli-boxes: ^3.0.0 + string-width: ^5.1.2 + type-fest: ^2.13.0 + widest-line: ^4.0.1 + wrap-ansi: ^8.1.0 + checksum: ad8833d5f2845b0a728fdf8a0bc1505dff0c518edcb0fd56979a08774b1f26cf48b71e66532179ccdfb9ed95b64aa008689cca26f7776f93f002b8000a683d76 + languageName: node + linkType: hard + "bplist-parser@npm:^0.2.0": version: 0.2.0 resolution: "bplist-parser@npm:0.2.0" @@ -6554,17 +7234,17 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.18.1, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.21.9, browserslist@npm:^4.22.1": - version: 4.22.1 - resolution: "browserslist@npm:4.22.1" +"browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.18.1, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.21.9, browserslist@npm:^4.22.2": + version: 4.22.2 + resolution: "browserslist@npm:4.22.2" dependencies: - caniuse-lite: ^1.0.30001541 - electron-to-chromium: ^1.4.535 - node-releases: ^2.0.13 + caniuse-lite: ^1.0.30001565 + electron-to-chromium: ^1.4.601 + node-releases: ^2.0.14 update-browserslist-db: ^1.0.13 bin: browserslist: cli.js - checksum: 7e6b10c53f7dd5d83fd2b95b00518889096382539fed6403829d447e05df4744088de46a571071afb447046abc3c66ad06fbc790e70234ec2517452e32ffd862 + checksum: 33ddfcd9145220099a7a1ac533cecfe5b7548ffeb29b313e1b57be6459000a1f8fa67e781cf4abee97268ac594d44134fcc4a6b2b4750ceddc9796e3a22076d9 languageName: node linkType: hard @@ -6659,23 +7339,23 @@ __metadata: languageName: node linkType: hard -"cacache@npm:^17.0.0": - version: 17.1.4 - resolution: "cacache@npm:17.1.4" +"cacache@npm:^18.0.0": + version: 18.0.1 + resolution: "cacache@npm:18.0.1" dependencies: "@npmcli/fs": ^3.1.0 fs-minipass: ^3.0.0 glob: ^10.2.2 - lru-cache: ^7.7.1 + lru-cache: ^10.0.1 minipass: ^7.0.3 - minipass-collect: ^1.0.2 + minipass-collect: ^2.0.1 minipass-flush: ^1.0.5 minipass-pipeline: ^1.2.4 p-map: ^4.0.0 ssri: ^10.0.0 tar: ^6.1.11 unique-filename: ^3.0.0 - checksum: b7751df756656954a51201335addced8f63fc53266fa56392c9f5ae83c8d27debffb4458ac2d168a744a4517ec3f2163af05c20097f93d17bdc2dc8a385e14a6 + checksum: 5a0b3b2ea451a0379814dc1d3c81af48c7c6db15cd8f7d72e028501ae0036a599a99bbac9687bfec307afb2760808d1c7708e9477c8c70d2b166e7d80b162a23 languageName: node linkType: hard @@ -6689,6 +7369,28 @@ __metadata: languageName: node linkType: hard +"cacheable-lookup@npm:^7.0.0": + version: 7.0.0 + resolution: "cacheable-lookup@npm:7.0.0" + checksum: 9e2856763fc0a7347ab34d704c010440b819d4bb5e3593b664381b7433e942dd22e67ee5581f12256f908e79b82d30b86ebbacf40a081bfe10ee93fbfbc2d6a9 + languageName: node + linkType: hard + +"cacheable-request@npm:^10.2.8": + version: 10.2.14 + resolution: "cacheable-request@npm:10.2.14" + dependencies: + "@types/http-cache-semantics": ^4.0.2 + get-stream: ^6.0.1 + http-cache-semantics: ^4.1.1 + keyv: ^4.5.3 + mimic-response: ^4.0.0 + normalize-url: ^8.0.0 + responselike: ^3.0.0 + checksum: 56f2b8e1c497c91f8391f0b099d19907a7dde25e71087e622b23e45fc8061736c2a6964ef121b16f377c3c61079cf8dc17320ab54004209d1343e4d26aba7015 + languageName: node + linkType: hard + "cacheable-request@npm:^6.0.0": version: 6.1.0 resolution: "cacheable-request@npm:6.1.0" @@ -6704,13 +7406,14 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2": - version: 1.0.2 - resolution: "call-bind@npm:1.0.2" +"call-bind@npm:^1.0.0, call-bind@npm:^1.0.5": + version: 1.0.5 + resolution: "call-bind@npm:1.0.5" dependencies: - function-bind: ^1.1.1 - get-intrinsic: ^1.0.2 - checksum: f8e31de9d19988a4b80f3e704788c4a2d6b6f3d17cfec4f57dc29ced450c53a49270dc66bf0fbd693329ee948dd33e6c90a329519aef17474a4d961e8d6426b0 + function-bind: ^1.1.2 + get-intrinsic: ^1.2.1 + set-function-length: ^1.1.1 + checksum: 449e83ecbd4ba48e7eaac5af26fea3b50f8f6072202c2dd7c5a6e7a6308f2421abe5e13a3bbd55221087f76320c5e09f25a8fdad1bab2b77c68ae74d92234ea5 languageName: node linkType: hard @@ -6721,13 +7424,6 @@ __metadata: languageName: node linkType: hard -"callsites@npm:^4.0.0": - version: 4.1.0 - resolution: "callsites@npm:4.1.0" - checksum: 4ad31de7b7615fa25bdab9c2373865209d2d5190f895cdf2e2f518bd1dafa7ebcda2e6e9cc9640f2dfde6b3893d82fa4359a78ffc27baad2503227553c6882fa - languageName: node - linkType: hard - "camel-case@npm:^4.1.2": version: 4.1.2 resolution: "camel-case@npm:4.1.2" @@ -6752,6 +7448,13 @@ __metadata: languageName: node linkType: hard +"camelcase@npm:^7.0.0, camelcase@npm:^7.0.1": + version: 7.0.1 + resolution: "camelcase@npm:7.0.1" + checksum: 86ab8f3ebf08bcdbe605a211a242f00ed30d8bfb77dab4ebb744dd36efbc84432d1c4adb28975ba87a1b8be40a80fbd1e60e2f06565315918fa7350011a26d3d + languageName: node + linkType: hard + "caniuse-api@npm:^3.0.0": version: 3.0.0 resolution: "caniuse-api@npm:3.0.0" @@ -6764,10 +7467,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001541": - version: 1.0.30001549 - resolution: "caniuse-lite@npm:1.0.30001549" - checksum: 7f2abeedc8cf8b92cc0613855d71b995ce436068c0bcdd798c5af7d297ccf9f52496b00181beda42d82d25079dd4b6e389c67486156d40d8854e5707a25cb054 +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001565": + version: 1.0.30001568 + resolution: "caniuse-lite@npm:1.0.30001568" + checksum: 7092aaa246dc8531fbca5b47be91e92065db7e5c04cc9e3d864e848f8f1be769ac6754429e843a5e939f7331a771e8b0a1bc3b13495c66b748c65e2f5bdb1220 languageName: node linkType: hard @@ -6785,15 +7488,6 @@ __metadata: languageName: node linkType: hard -"cbor@npm:^8.1.0": - version: 8.1.0 - resolution: "cbor@npm:8.1.0" - dependencies: - nofilter: ^3.1.0 - checksum: a90338435dc7b45cc01461af979e3bb6ddd4f2a08584c437586039cd5f2235014c06e49d664295debbfb3514d87b2f06728092ab6aa6175e2e85e9cd7dc0c1fd - languageName: node - linkType: hard - "ccount@npm:^1.0.0": version: 1.1.0 resolution: "ccount@npm:1.1.0" @@ -6801,6 +7495,13 @@ __metadata: languageName: node linkType: hard +"ccount@npm:^2.0.0": + version: 2.0.1 + resolution: "ccount@npm:2.0.1" + checksum: 48193dada54c9e260e0acf57fc16171a225305548f9ad20d5471e0f7a8c026aedd8747091dccb0d900cde7df4e4ddbd235df0d8de4a64c71b12f0d3303eeafd4 + languageName: node + linkType: hard + "chai-as-promised@npm:^7.1.1": version: 7.1.1 resolution: "chai-as-promised@npm:7.1.1" @@ -6813,21 +7514,21 @@ __metadata: linkType: hard "chai@npm:^4.3.7, chai@npm:^4.3.8": - version: 4.3.8 - resolution: "chai@npm:4.3.8" + version: 4.3.10 + resolution: "chai@npm:4.3.10" dependencies: assertion-error: ^1.1.0 - check-error: ^1.0.2 - deep-eql: ^4.1.2 - get-func-name: ^2.0.0 - loupe: ^2.3.1 + check-error: ^1.0.3 + deep-eql: ^4.1.3 + get-func-name: ^2.0.2 + loupe: ^2.3.6 pathval: ^1.1.1 - type-detect: ^4.0.5 - checksum: 29e0984ed13308319cadc35437c8ef0a3e271544d226c991bf7e3b6d771bf89707321669e11d05e362bc0ad0bd26585079b989d1032f3c106e3bb95d7f079cce + type-detect: ^4.0.8 + checksum: 536668c60a0d985a0fbd94418028e388d243a925d7c5e858c7443e334753511614a3b6a124bac9ca077dfc4c37acc367d62f8c294960f440749536dc181dfc6d languageName: node linkType: hard -"chalk-template@npm:^0.4.0": +"chalk-template@npm:0.4.0, chalk-template@npm:^0.4.0": version: 0.4.0 resolution: "chalk-template@npm:0.4.0" dependencies: @@ -6836,6 +7537,13 @@ __metadata: languageName: node linkType: hard +"chalk@npm:5.0.1": + version: 5.0.1 + resolution: "chalk@npm:5.0.1" + checksum: 7b45300372b908f0471fbf7389ce2f5de8d85bb949026fd51a1b95b10d0ed32c7ed5aab36dd5e9d2bf3191867909b4404cef75c5f4d2d1daeeacd301dd280b76 + languageName: node + linkType: hard + "chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" @@ -6864,6 +7572,20 @@ __metadata: languageName: node linkType: hard +"char-regex@npm:^1.0.2": + version: 1.0.2 + resolution: "char-regex@npm:1.0.2" + checksum: b563e4b6039b15213114626621e7a3d12f31008bdce20f9c741d69987f62aeaace7ec30f6018890ad77b2e9b4d95324c9f5acfca58a9441e3b1dcdd1e2525d17 + languageName: node + linkType: hard + +"character-entities-html4@npm:^2.0.0": + version: 2.1.0 + resolution: "character-entities-html4@npm:2.1.0" + checksum: 7034aa7c7fa90309667f6dd50499c8a760c3d3a6fb159adb4e0bada0107d194551cdbad0714302f62d06ce4ed68565c8c2e15fdef2e8f8764eb63fa92b34b11d + languageName: node + linkType: hard + "character-entities-legacy@npm:^1.0.0": version: 1.1.4 resolution: "character-entities-legacy@npm:1.1.4" @@ -6871,6 +7593,13 @@ __metadata: languageName: node linkType: hard +"character-entities-legacy@npm:^3.0.0": + version: 3.0.0 + resolution: "character-entities-legacy@npm:3.0.0" + checksum: 7582af055cb488b626d364b7d7a4e46b06abd526fb63c0e4eb35bcb9c9799cc4f76b39f34fdccef2d1174ac95e53e9ab355aae83227c1a2505877893fce77731 + languageName: node + linkType: hard + "character-entities@npm:^1.0.0": version: 1.2.4 resolution: "character-entities@npm:1.2.4" @@ -6878,6 +7607,13 @@ __metadata: languageName: node linkType: hard +"character-entities@npm:^2.0.0": + version: 2.0.2 + resolution: "character-entities@npm:2.0.2" + checksum: cf1643814023697f725e47328fcec17923b8f1799102a8a79c1514e894815651794a2bffd84bb1b3a4b124b050154e4529ed6e81f7c8068a734aecf07a6d3def + languageName: node + linkType: hard + "character-reference-invalid@npm:^1.0.0": version: 1.1.4 resolution: "character-reference-invalid@npm:1.1.4" @@ -6885,10 +7621,19 @@ __metadata: languageName: node linkType: hard -"check-error@npm:^1.0.2": - version: 1.0.2 - resolution: "check-error@npm:1.0.2" - checksum: d9d106504404b8addd1ee3f63f8c0eaa7cd962a1a28eb9c519b1c4a1dc7098be38007fc0060f045ee00f075fbb7a2a4f42abcf61d68323677e11ab98dc16042e +"character-reference-invalid@npm:^2.0.0": + version: 2.0.1 + resolution: "character-reference-invalid@npm:2.0.1" + checksum: 98d3b1a52ae510b7329e6ee7f6210df14f1e318c5415975d4c9e7ee0ef4c07875d47c6e74230c64551f12f556b4a8ccc24d9f3691a2aa197019e72a95e9297ee + languageName: node + linkType: hard + +"check-error@npm:^1.0.2, check-error@npm:^1.0.3": + version: 1.0.3 + resolution: "check-error@npm:1.0.3" + dependencies: + get-func-name: ^2.0.2 + checksum: e2131025cf059b21080f4813e55b3c480419256914601750b0fee3bd9b2b8315b531e551ef12560419b8b6d92a3636511322752b1ce905703239e7cc451b6399 languageName: node linkType: hard @@ -6986,13 +7731,6 @@ __metadata: languageName: node linkType: hard -"chunkd@npm:^2.0.1": - version: 2.0.1 - resolution: "chunkd@npm:2.0.1" - checksum: bab8cc08c752a3648984385dc6f61d751e89dbeef648d22a3b661e1d470eaa0f5182f0b4303710f13ae83d2f85144f8eb2dde7a975861d9021b5c56b881f457b - languageName: node - linkType: hard - "ci-info@npm:^2.0.0": version: 2.0.0 resolution: "ci-info@npm:2.0.0" @@ -7007,20 +7745,6 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:^3.8.0": - version: 3.8.0 - resolution: "ci-info@npm:3.8.0" - checksum: d0a4d3160497cae54294974a7246202244fff031b0a6ea20dd57b10ec510aa17399c41a1b0982142c105f3255aff2173e5c0dd7302ee1b2f28ba3debda375098 - languageName: node - linkType: hard - -"ci-parallel-vars@npm:^1.0.1": - version: 1.0.1 - resolution: "ci-parallel-vars@npm:1.0.1" - checksum: ae859831f7e8e3585db731b8306c336616e37bd709dad1d7775ea4c0731aefd94741dabb48201edc6827d000008fd7fb72cb977967614ee2d99d6b499f0c35fe - languageName: node - linkType: hard - "cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": version: 1.0.4 resolution: "cipher-base@npm:1.0.4" @@ -7045,12 +7769,12 @@ __metadata: languageName: node linkType: hard -"clean-css@npm:^5.2.2, clean-css@npm:^5.3.0": - version: 5.3.2 - resolution: "clean-css@npm:5.3.2" +"clean-css@npm:^5.2.2, clean-css@npm:^5.3.0, clean-css@npm:^5.3.2, clean-css@npm:~5.3.2": + version: 5.3.3 + resolution: "clean-css@npm:5.3.3" dependencies: source-map: ~0.6.0 - checksum: 8787b281acc9878f309b5f835d410085deedfd4e126472666773040a6a8a72f472a1d24185947d23b87b1c419bf2c5ed429395d5c5ff8279c98b05d8011e9758 + checksum: 941987c14860dd7d346d5cf121a82fd2caf8344160b1565c5387f7ccca4bbcaf885bace961be37c4f4713ce2d8c488dd89483c1add47bb779790edbfdcc79cbc languageName: node linkType: hard @@ -7061,22 +7785,6 @@ __metadata: languageName: node linkType: hard -"clean-stack@npm:^4.0.0": - version: 4.2.0 - resolution: "clean-stack@npm:4.2.0" - dependencies: - escape-string-regexp: 5.0.0 - checksum: 373f656a31face5c615c0839213b9b542a0a48057abfb1df66900eab4dc2a5c6097628e4a0b5aa559cdfc4e66f8a14ea47be9681773165a44470ef5fb8ccc172 - languageName: node - linkType: hard - -"clean-yaml-object@npm:^0.1.0": - version: 0.1.0 - resolution: "clean-yaml-object@npm:0.1.0" - checksum: 0374ad2f1fbd4984ecf56ebc62200092f6372b9ccf1b7971bb979c328fb12fe76e759fb1e8adc491c80b7b1861f9f00c7f19813dd2a0f49c88231422c70451f4 - languageName: node - linkType: hard - "cli-boxes@npm:^2.2.1": version: 2.2.1 resolution: "cli-boxes@npm:2.2.1" @@ -7100,7 +7808,7 @@ __metadata: languageName: node linkType: hard -"cli-table3@npm:^0.6.2": +"cli-table3@npm:^0.6.2, cli-table3@npm:^0.6.3": version: 0.6.3 resolution: "cli-table3@npm:0.6.3" dependencies: @@ -7113,13 +7821,14 @@ __metadata: languageName: node linkType: hard -"cli-truncate@npm:^3.1.0": - version: 3.1.0 - resolution: "cli-truncate@npm:3.1.0" +"clipboardy@npm:3.0.0": + version: 3.0.0 + resolution: "clipboardy@npm:3.0.0" dependencies: - slice-ansi: ^5.0.0 - string-width: ^5.0.0 - checksum: c3243e41974445691c63f8b405df1d5a24049dc33d324fe448dc572e561a7b772ae982692900b1a5960901cc4fc7def25a629b9c69a4208ee89d12ab3332617a + arch: ^2.2.0 + execa: ^5.1.1 + is-wsl: ^2.2.0 + checksum: 2c292acb59705494cbe07d7df7c8becff4f01651514d32ebd80f4aec2d20946d8f3824aac67ecdf2d09ef21fdf0eb24b6a7f033c137ccdceedc4661c54455c94 languageName: node linkType: hard @@ -7179,6 +7888,13 @@ __metadata: languageName: node linkType: hard +"clsx@npm:^2.0.0": + version: 2.0.0 + resolution: "clsx@npm:2.0.0" + checksum: a2cfb2351b254611acf92faa0daf15220f4cd648bdf96ce369d729813b85336993871a4bf6978ddea2b81b5a130478339c20d9d0b5c6fc287e5147f0c059276e + languageName: node + linkType: hard + "co-body@npm:^6.1.0": version: 6.1.0 resolution: "co-body@npm:6.1.0" @@ -7198,15 +7914,6 @@ __metadata: languageName: node linkType: hard -"code-excerpt@npm:^4.0.0": - version: 4.0.0 - resolution: "code-excerpt@npm:4.0.0" - dependencies: - convert-to-spaces: ^2.0.1 - checksum: d57137d8f4825879283a828cc02a1115b56858dc54ed06c625c8f67d6685d1becd2fbaa7f0ab19ecca1f5cca03f8c97bbc1f013cab40261e4d3275032e65efe9 - languageName: node - linkType: hard - "collapse-white-space@npm:^1.0.2": version: 1.0.6 resolution: "collapse-white-space@npm:1.0.6" @@ -7214,6 +7921,13 @@ __metadata: languageName: node linkType: hard +"collapse-white-space@npm:^2.0.0": + version: 2.1.0 + resolution: "collapse-white-space@npm:2.1.0" + checksum: c8978b1f4e7d68bf846cfdba6c6689ce8910511df7d331eb6e6757e51ceffb52768d59a28db26186c91dcf9594955b59be9f8ccd473c485790f5d8b90dc6726f + languageName: node + linkType: hard + "color-convert@npm:^1.9.0": version: 1.9.3 resolution: "color-convert@npm:1.9.3" @@ -7246,15 +7960,6 @@ __metadata: languageName: node linkType: hard -"color-support@npm:^1.1.3": - version: 1.1.3 - resolution: "color-support@npm:1.1.3" - bin: - color-support: bin.js - checksum: 9b7356817670b9a13a26ca5af1c21615463b500783b739b7634a0c2047c16cef4b2865d7576875c31c3cddf9dd621fa19285e628f20198b233a5cfdda6d0793b - languageName: node - linkType: hard - "colord@npm:^2.9.1": version: 2.9.3 resolution: "colord@npm:2.9.3" @@ -7299,6 +8004,13 @@ __metadata: languageName: node linkType: hard +"comma-separated-tokens@npm:^2.0.0": + version: 2.0.3 + resolution: "comma-separated-tokens@npm:2.0.3" + checksum: e3bf9e0332a5c45f49b90e79bcdb4a7a85f28d6a6f0876a94f1bb9b2bfbdbbb9292aac50e1e742d8c0db1e62a0229a106f57917e2d067fca951d81737651700d + languageName: node + linkType: hard + "command-exists@npm:^1.2.8": version: 1.2.9 resolution: "command-exists@npm:1.2.9" @@ -7349,7 +8061,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^10.0.1": +"commander@npm:^10.0.0, commander@npm:^10.0.1": version: 10.0.1 resolution: "commander@npm:10.0.1" checksum: 436901d64a818295803c1996cd856621a74f30b9f9e28a588e726b2b1670665bccd7c1a77007ebf328729f0139838a88a19265858a0fa7a8728c4656796db948 @@ -7377,7 +8089,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^8.0.0, commander@npm:^8.3.0": +"commander@npm:^8.3.0": version: 8.3.0 resolution: "commander@npm:8.3.0" checksum: 0f82321821fc27b83bd409510bb9deeebcfa799ff0bf5d102128b500b7af22872c0c92cb6a0ebc5a4cf19c6b550fba9cedfa7329d18c6442a625f851377bacf0 @@ -7407,7 +8119,7 @@ __metadata: languageName: node linkType: hard -"compression@npm:^1.7.4": +"compression@npm:1.7.4, compression@npm:^1.7.4": version: 1.7.4 resolution: "compression@npm:1.7.4" dependencies: @@ -7429,19 +8141,13 @@ __metadata: languageName: node linkType: hard -"concordance@npm:^5.0.4": - version: 5.0.4 - resolution: "concordance@npm:5.0.4" +"config-chain@npm:^1.1.11": + version: 1.1.13 + resolution: "config-chain@npm:1.1.13" dependencies: - date-time: ^3.1.0 - esutils: ^2.0.3 - fast-diff: ^1.2.0 - js-string-escape: ^1.0.1 - lodash: ^4.17.15 - md5-hex: ^3.0.1 - semver: ^7.3.2 - well-known-symbols: ^2.0.0 - checksum: 749153ba711492feb7c3d2f5bb04c107157440b3e39509bd5dd19ee7b3ac751d1e4cd75796d9f702e0a713312dbc661421c68aa4a2c34d5f6d91f47e3a1c64a6 + ini: ^1.3.4 + proto-list: ~1.2.1 + checksum: 828137a28e7c2fc4b7fb229bd0cd6c1397bcf83434de54347e608154008f411749041ee392cbe42fab6307e02de4c12480260bf769b7d44b778fdea3839eafab languageName: node linkType: hard @@ -7459,6 +8165,19 @@ __metadata: languageName: node linkType: hard +"configstore@npm:^6.0.0": + version: 6.0.0 + resolution: "configstore@npm:6.0.0" + dependencies: + dot-prop: ^6.0.1 + graceful-fs: ^4.2.6 + unique-string: ^3.0.0 + write-file-atomic: ^3.0.3 + xdg-basedir: ^5.0.1 + checksum: 81995351c10bc04c58507f17748477aeac6f47465109d20e3534cebc881d22e927cfd29e73dd852c46c55f62c2b7be4cd1fe6eb3a93ba51f7f9813c218f9bae0 + languageName: node + linkType: hard + "connect-history-api-fallback@npm:^2.0.0": version: 2.0.0 resolution: "connect-history-api-fallback@npm:2.0.0" @@ -7473,13 +8192,6 @@ __metadata: languageName: node linkType: hard -"console-control-strings@npm:^1.1.0": - version: 1.1.0 - resolution: "console-control-strings@npm:1.1.0" - checksum: 8755d76787f94e6cf79ce4666f0c5519906d7f5b02d4b884cf41e11dcd759ed69c57da0670afd9236d229a46e0f9cf519db0cd829c6dca820bb5a5c3def584ed - languageName: node - linkType: hard - "content-disposition@npm:0.5.2": version: 0.5.2 resolution: "content-disposition@npm:0.5.2" @@ -7503,7 +8215,7 @@ __metadata: languageName: node linkType: hard -"convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": +"convert-source-map@npm:^1.7.0": version: 1.9.0 resolution: "convert-source-map@npm:1.9.0" checksum: dc55a1f28ddd0e9485ef13565f8f756b342f9a46c4ae18b843fe3c30c675d058d6a4823eff86d472f187b176f0adf51ea7b69ea38be34be4a63cbbf91b0593c8 @@ -7517,13 +8229,6 @@ __metadata: languageName: node linkType: hard -"convert-to-spaces@npm:^2.0.1": - version: 2.0.1 - resolution: "convert-to-spaces@npm:2.0.1" - checksum: bbb324e5916fe9866f65c0ff5f9c1ea933764d0bdb09fccaf59542e40545ed483db6b2339c6d9eb56a11965a58f1a6038f3174f0e2fb7601343c7107ca5e2751 - languageName: node - linkType: hard - "cookie-signature@npm:1.0.6": version: 1.0.6 resolution: "cookie-signature@npm:1.0.6" @@ -7555,7 +8260,7 @@ __metadata: languageName: node linkType: hard -"copy-text-to-clipboard@npm:^3.0.1": +"copy-text-to-clipboard@npm:^3.2.0": version: 3.2.0 resolution: "copy-text-to-clipboard@npm:3.2.0" checksum: df7115c197a166d51f59e4e20ab2a68a855ae8746d25ff149b5465c694d9a405c7e6684b73a9f87ba8d653070164e229c15dfdb9fd77c30be1ff0da569661060 @@ -7578,26 +8283,26 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.32.2": - version: 3.33.0 - resolution: "core-js-compat@npm:3.33.0" +"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1": + version: 3.34.0 + resolution: "core-js-compat@npm:3.34.0" dependencies: - browserslist: ^4.22.1 - checksum: 83ae54008c09b8e0ae3c59457039866c342c7e28b0d30eebb638a5b51c01432e63fe97695c90645cbc6a8b073a4f9a8b0e75f0818bbf8b4b054e01f4c17d3181 + browserslist: ^4.22.2 + checksum: 6281f7f57a72f254c06611ec088445e11cf84e0b4edfb5f43dece1a1ff8b0ed0e81ed0bc291024761cd90c39d0f007d8bc46548265139808081d311c7cbc9c81 languageName: node linkType: hard "core-js-pure@npm:^3.30.2": - version: 3.33.0 - resolution: "core-js-pure@npm:3.33.0" - checksum: d47084a4de9a0cef9779eccd3ac9f435cf9fd7aa71794150cd4c6b305036bcc392d94766d4a7b6456bdd08faba7752d55c2ec40185bda161c3563081c9fa1e17 + version: 3.34.0 + resolution: "core-js-pure@npm:3.34.0" + checksum: 4c44ac4beff42e07f41eef3c9ecefc8ee3f9e91e1b9f278bf8520cc1fb37afb663cff77c182541dc42d58737f93ab0f30a33a5fe661fb161fdd8aa7fe78a5edf languageName: node linkType: hard -"core-js@npm:^3.23.3": - version: 3.33.0 - resolution: "core-js@npm:3.33.0" - checksum: dd62217935ac281faf6f833bb306fb891162919fcf9c1f0c975b1b91e82ac09a940f5deb5950bbb582739ceef716e8bd7e4f9eab8328932fb029d3bc2ecb2881 +"core-js@npm:^3.23.3, core-js@npm:^3.31.1": + version: 3.34.0 + resolution: "core-js@npm:3.34.0" + checksum: 26b0d103716b33fc660ee8737da7bc9475fbc655f93bbf1360ab692966449d18f2fc393805095937283db9f919ca2aa5c88d86d16f2846217983ad7da707e31e languageName: node linkType: hard @@ -7703,15 +8408,6 @@ __metadata: languageName: node linkType: hard -"cross-fetch@npm:^3.1.5": - version: 3.1.8 - resolution: "cross-fetch@npm:3.1.8" - dependencies: - node-fetch: ^2.6.12 - checksum: 78f993fa099eaaa041122ab037fe9503ecbbcb9daef234d1d2e0b9230a983f64d645d088c464e21a247b825a08dc444a6e7064adfa93536d3a9454b4745b3632 - languageName: node - linkType: hard - "cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -7730,6 +8426,15 @@ __metadata: languageName: node linkType: hard +"crypto-random-string@npm:^4.0.0": + version: 4.0.0 + resolution: "crypto-random-string@npm:4.0.0" + dependencies: + type-fest: ^1.0.1 + checksum: 91f148f27bcc8582798f0fb3e75a09d9174557f39c3c40a89dd1bd70fb5a14a02548245aa26fa7d663c426ac5026f4729841231c84f9e30e8c8ece5e38656741 + languageName: node + linkType: hard + "css-declaration-sorter@npm:^6.3.1": version: 6.4.1 resolution: "css-declaration-sorter@npm:6.4.1" @@ -7739,7 +8444,7 @@ __metadata: languageName: node linkType: hard -"css-loader@npm:^6.7.1": +"css-loader@npm:^6.7.1, css-loader@npm:^6.8.1": version: 6.8.1 resolution: "css-loader@npm:6.8.1" dependencies: @@ -7757,7 +8462,7 @@ __metadata: languageName: node linkType: hard -"css-minimizer-webpack-plugin@npm:^4.0.0": +"css-minimizer-webpack-plugin@npm:^4.0.0, css-minimizer-webpack-plugin@npm:^4.2.2": version: 4.2.2 resolution: "css-minimizer-webpack-plugin@npm:4.2.2" dependencies: @@ -7838,7 +8543,7 @@ __metadata: languageName: node linkType: hard -"cssnano-preset-advanced@npm:^5.3.8": +"cssnano-preset-advanced@npm:^5.3.10, cssnano-preset-advanced@npm:^5.3.8": version: 5.3.10 resolution: "cssnano-preset-advanced@npm:5.3.10" dependencies: @@ -7902,7 +8607,7 @@ __metadata: languageName: node linkType: hard -"cssnano@npm:^5.1.12, cssnano@npm:^5.1.8": +"cssnano@npm:^5.1.12, cssnano@npm:^5.1.15, cssnano@npm:^5.1.8": version: 5.1.15 resolution: "cssnano@npm:5.1.15" dependencies: @@ -7925,18 +8630,9 @@ __metadata: linkType: hard "csstype@npm:^3.0.2": - version: 3.1.2 - resolution: "csstype@npm:3.1.2" - checksum: e1a52e6c25c1314d6beef5168da704ab29c5186b877c07d822bd0806717d9a265e8493a2e35ca7e68d0f5d472d43fac1cdce70fd79fd0853dff81f3028d857b5 - languageName: node - linkType: hard - -"currently-unhandled@npm:^0.4.1": - version: 0.4.1 - resolution: "currently-unhandled@npm:0.4.1" - dependencies: - array-find-index: ^1.0.1 - checksum: 1f59fe10b5339b54b1a1eee110022f663f3495cf7cf2f480686e89edc7fa8bfe42dbab4b54f85034bc8b092a76cc7becbc2dad4f9adad332ab5831bec39ad540 + version: 3.1.3 + resolution: "csstype@npm:3.1.3" + checksum: 8db785cc92d259102725b3c694ec0c823f5619a84741b5c7991b8ad135dfaa66093038a1cc63e03361a6cd28d122be48f2106ae72334e067dd619a51f49eddf7 languageName: node linkType: hard @@ -7947,16 +8643,7 @@ __metadata: languageName: node linkType: hard -"date-time@npm:^3.1.0": - version: 3.1.0 - resolution: "date-time@npm:3.1.0" - dependencies: - time-zone: ^1.0.0 - checksum: f9cfcd1b15dfeabab15c0b9d18eb9e4e2d9d4371713564178d46a8f91ad577a290b5178b80050718d02d9c0cf646f8a875011e12d1ed05871e9f72c72c8a8fe6 - languageName: node - linkType: hard - -"debounce@npm:^1.2.0": +"debounce@npm:^1.2.0, debounce@npm:^1.2.1": version: 1.2.1 resolution: "debounce@npm:1.2.1" checksum: 682a89506d9e54fb109526f4da255c5546102fbb8e3ae75eef3b04effaf5d4853756aee97475cd4650641869794e44f410eeb20ace2b18ea592287ab2038519e @@ -7972,7 +8659,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.2.0, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.2.0, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -8000,6 +8687,15 @@ __metadata: languageName: node linkType: hard +"decode-named-character-reference@npm:^1.0.0": + version: 1.0.2 + resolution: "decode-named-character-reference@npm:1.0.2" + dependencies: + character-entities: ^2.0.0 + checksum: f4c71d3b93105f20076052f9cb1523a22a9c796b8296cd35eef1ca54239c78d182c136a848b83ff8da2071e3ae2b1d300bf29d00650a6d6e675438cc31b11d78 + languageName: node + linkType: hard + "decompress-response@npm:^3.3.0": version: 3.3.0 resolution: "decompress-response@npm:3.3.0" @@ -8009,7 +8705,16 @@ __metadata: languageName: node linkType: hard -"deep-eql@npm:^4.0.1, deep-eql@npm:^4.1.2": +"decompress-response@npm:^6.0.0": + version: 6.0.0 + resolution: "decompress-response@npm:6.0.0" + dependencies: + mimic-response: ^3.1.0 + checksum: d377cf47e02d805e283866c3f50d3d21578b779731e8c5072d6ce8c13cc31493db1c2f6784da9d1d5250822120cefa44f1deab112d5981015f2e17444b763812 + languageName: node + linkType: hard + +"deep-eql@npm:^4.0.1, deep-eql@npm:^4.1.3": version: 4.1.3 resolution: "deep-eql@npm:4.1.3" dependencies: @@ -8084,7 +8789,14 @@ __metadata: languageName: node linkType: hard -"define-data-property@npm:^1.0.1": +"defer-to-connect@npm:^2.0.1": + version: 2.0.1 + resolution: "defer-to-connect@npm:2.0.1" + checksum: 8a9b50d2f25446c0bfefb55a48e90afd58f85b21bcf78e9207cd7b804354f6409032a1705c2491686e202e64fc05f147aa5aa45f9aa82627563f045937f5791b + languageName: node + linkType: hard + +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1": version: 1.1.1 resolution: "define-data-property@npm:1.1.1" dependencies: @@ -8109,7 +8821,7 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.1.4": +"define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -8214,7 +8926,7 @@ __metadata: languageName: node linkType: hard -"detect-port@npm:^1.3.0": +"detect-port@npm:^1.3.0, detect-port@npm:^1.5.1": version: 1.5.1 resolution: "detect-port@npm:1.5.1" dependencies: @@ -8227,6 +8939,15 @@ __metadata: languageName: node linkType: hard +"devlop@npm:^1.0.0, devlop@npm:^1.1.0": + version: 1.1.0 + resolution: "devlop@npm:1.1.0" + dependencies: + dequal: ^2.0.0 + checksum: d2ff650bac0bb6ef08c48f3ba98640bb5fec5cce81e9957eb620408d1bab1204d382a45b785c6b3314dc867bb0684936b84c6867820da6db97cbb5d3c15dd185 + languageName: node + linkType: hard + "devtools-protocol@npm:0.0.1107588": version: 0.0.1107588 resolution: "devtools-protocol@npm:0.0.1107588" @@ -8284,26 +9005,37 @@ __metadata: version: 0.0.0-use.local resolution: "docs@workspace:docs" dependencies: - "@docusaurus/core": ^2.4.0 - "@docusaurus/module-type-aliases": ^2.4.0 - "@docusaurus/plugin-google-gtag": ^2.4.0 - "@docusaurus/preset-classic": ^2.4.0 + "@docusaurus/core": ^3.0.1 + "@docusaurus/module-type-aliases": ^3.0.1 + "@docusaurus/preset-classic": ^3.0.1 + "@docusaurus/tsconfig": ^3.0.1 + "@docusaurus/types": ^3.0.1 "@easyops-cn/docusaurus-search-local": ^0.35.0 - "@mdx-js/react": ^1.6.22 + "@mdx-js/react": ^3.0.0 + "@noir-lang/noir_js": "workspace:*" + "@noir-lang/noirc_abi": "workspace:*" + "@noir-lang/types": "workspace:*" + "@signorecello/noir_playground": ^0.6.0 + "@types/prettier": ^3 axios: ^1.4.0 clsx: ^1.2.1 docusaurus-plugin-typedoc: 1.0.0-next.18 + eslint-plugin-prettier: ^5.0.0 hast-util-is-element: ^1.1.0 - prism-react-renderer: ^1.3.5 - react: ^17.0.2 - react-dom: ^17.0.2 - rehype-katex: ^5.0.0 - remark-math: ^3.0.1 + prettier: 3.0.3 + prism-react-renderer: ^2.1.0 + react: ^18.2.0 + react-dom: ^18.2.0 + react-spinners: ^0.13.8 + rehype-katex: ^7.0.0 + remark-math: ^6.0.0 + serve: ^14.2.1 + ts-node: ^10.9.1 typedoc: ^0.25.0 typedoc-plugin-frontmatter: ^0.0.2 typedoc-plugin-markdown: 4.0.0-next.25 typedoc-plugin-merge-modules: ^5.1.0 - typescript: ^5.2.2 + typescript: ~5.2.2 languageName: unknown linkType: soft @@ -8424,6 +9156,15 @@ __metadata: languageName: node linkType: hard +"dot-prop@npm:^6.0.1": + version: 6.0.1 + resolution: "dot-prop@npm:6.0.1" + dependencies: + is-obj: ^2.0.0 + checksum: 0f47600a4b93e1dc37261da4e6909652c008832a5d3684b5bf9a9a0d3f4c67ea949a86dceed9b72f5733ed8e8e6383cc5958df3bbd0799ee317fd181f2ece700 + languageName: node + linkType: hard + "duplexer3@npm:^0.1.4": version: 0.1.5 resolution: "duplexer3@npm:0.1.5" @@ -8452,10 +9193,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.535": - version: 1.4.554 - resolution: "electron-to-chromium@npm:1.4.554" - checksum: cbac43c50b43777327f4a7bf149ee3088c1da8b91bbcd80f78d2cc77bc52763f6d0941574499239d9caefd3430d3093f865e5f1093371418f7d6b70301eeae9b +"electron-to-chromium@npm:^1.4.601": + version: 1.4.609 + resolution: "electron-to-chromium@npm:1.4.609" + checksum: 4ef3c32b11adc01ed8227d7bdbe0978b436b817e6b3bd09f19b42afbf9affdb6ddf99f4d20a3b28a494772a2985df12ec95abca849a38cccb217c4ee338561bb languageName: node linkType: hard @@ -8474,13 +9215,6 @@ __metadata: languageName: node linkType: hard -"emittery@npm:^1.0.1": - version: 1.0.1 - resolution: "emittery@npm:1.0.1" - checksum: d95faee6ffb2e023cadaa6804265fea5298c53d079f170112af8dfae3e141761363ea4510966128259346418e3ec7639310fd75059ecce2423bf8afd07004226 - languageName: node - linkType: hard - "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -8495,6 +9229,13 @@ __metadata: languageName: node linkType: hard +"emojilib@npm:^2.4.0": + version: 2.4.0 + resolution: "emojilib@npm:2.4.0" + checksum: ea241c342abda5a86ffd3a15d8f4871a616d485f700e03daea38c6ce38205847cea9f6ff8d5e962c00516b004949cc96c6e37b05559ea71a0a496faba53b56da + languageName: node + linkType: hard + "emojis-list@npm:^3.0.0": version: 3.0.0 resolution: "emojis-list@npm:3.0.0" @@ -8509,6 +9250,13 @@ __metadata: languageName: node linkType: hard +"emoticon@npm:^4.0.1": + version: 4.0.1 + resolution: "emoticon@npm:4.0.1" + checksum: 991ab6421927601af4eb44036b60e3125759a4d81f32d2ad96b66e3491e2fdb6a026eeb6bffbfa66724592dca95235570785963607d16961ea73a62ecce715e2 + languageName: node + linkType: hard + "encodeurl@npm:^1.0.2, encodeurl@npm:~1.0.2": version: 1.0.2 resolution: "encodeurl@npm:1.0.2" @@ -8592,16 +9340,16 @@ __metadata: linkType: hard "errorstacks@npm:^2.2.0": - version: 2.4.0 - resolution: "errorstacks@npm:2.4.0" - checksum: 59186ccd26d8b782682a17aa8c96a71c5b977e7e073ec1648a5b59d11acb02348000921751c28a1a8a5bea37481369b2dab27e6330c5b8ddf3ae9b610dfc02bf + version: 2.4.1 + resolution: "errorstacks@npm:2.4.1" + checksum: 1b46bdd3c40d3e30dbb6945c0529ffbef6ccdf2260eeecff6cc1ee95b708ec732094597d6adaa53ffe18d045150b366e3f7472d8594946f430941bfa4ad54479 languageName: node linkType: hard "es-module-lexer@npm:^1.0.0, es-module-lexer@npm:^1.2.1": - version: 1.3.1 - resolution: "es-module-lexer@npm:1.3.1" - checksum: 3beafa7e171eb1e8cc45695edf8d51638488dddf65294d7911f8d6a96249da6a9838c87529262cc6ea53988d8272cec0f4bff93f476ed031a54ba3afb51a0ed3 + version: 1.4.1 + resolution: "es-module-lexer@npm:1.4.1" + checksum: a11b5a256d4e8e9c7d94c2fd87415ccd1591617b6edd847e064503f8eaece2d25e2e9078a02c5ce3ed5e83bb748f5b4820efbe78072c8beb07ac619c2edec35d languageName: node linkType: hard @@ -8682,11 +9430,88 @@ __metadata: languageName: node linkType: hard -"escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 - languageName: node +"esbuild@npm:~0.18.20": + version: 0.18.20 + resolution: "esbuild@npm:0.18.20" + dependencies: + "@esbuild/android-arm": 0.18.20 + "@esbuild/android-arm64": 0.18.20 + "@esbuild/android-x64": 0.18.20 + "@esbuild/darwin-arm64": 0.18.20 + "@esbuild/darwin-x64": 0.18.20 + "@esbuild/freebsd-arm64": 0.18.20 + "@esbuild/freebsd-x64": 0.18.20 + "@esbuild/linux-arm": 0.18.20 + "@esbuild/linux-arm64": 0.18.20 + "@esbuild/linux-ia32": 0.18.20 + "@esbuild/linux-loong64": 0.18.20 + "@esbuild/linux-mips64el": 0.18.20 + "@esbuild/linux-ppc64": 0.18.20 + "@esbuild/linux-riscv64": 0.18.20 + "@esbuild/linux-s390x": 0.18.20 + "@esbuild/linux-x64": 0.18.20 + "@esbuild/netbsd-x64": 0.18.20 + "@esbuild/openbsd-x64": 0.18.20 + "@esbuild/sunos-x64": 0.18.20 + "@esbuild/win32-arm64": 0.18.20 + "@esbuild/win32-ia32": 0.18.20 + "@esbuild/win32-x64": 0.18.20 + dependenciesMeta: + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 5d253614e50cdb6ec22095afd0c414f15688e7278a7eb4f3720a6dd1306b0909cf431e7b9437a90d065a31b1c57be60130f63fe3e8d0083b588571f31ee6ec7b + languageName: node + linkType: hard + +"escalade@npm:^3.1.1": + version: 3.1.1 + resolution: "escalade@npm:3.1.1" + checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 + languageName: node linkType: hard "escape-goat@npm:^2.0.0": @@ -8696,6 +9521,13 @@ __metadata: languageName: node linkType: hard +"escape-goat@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-goat@npm:4.0.0" + checksum: 7034e0025eec7b751074b837f10312c5b768493265bdad046347c0aadbc1e652776f7e5df94766473fecb5d3681169cc188fe9ccc1e22be53318c18be1671cc0 + languageName: node + linkType: hard + "escape-html@npm:^1.0.3, escape-html@npm:~1.0.3": version: 1.0.3 resolution: "escape-html@npm:1.0.3" @@ -8710,13 +9542,6 @@ __metadata: languageName: node linkType: hard -"escape-string-regexp@npm:5.0.0, escape-string-regexp@npm:^5.0.0": - version: 5.0.0 - resolution: "escape-string-regexp@npm:5.0.0" - checksum: 20daabe197f3cb198ec28546deebcf24b3dbb1a5a269184381b3116d12f0532e06007f4bc8da25669d6a7f8efb68db0758df4cd981f57bc5b57f521a3e12c59e - languageName: node - linkType: hard - "escape-string-regexp@npm:^1.0.5": version: 1.0.5 resolution: "escape-string-regexp@npm:1.0.5" @@ -8724,16 +9549,16 @@ __metadata: languageName: node linkType: hard -"escape-string-regexp@npm:^2.0.0": - version: 2.0.0 - resolution: "escape-string-regexp@npm:2.0.0" - checksum: 9f8a2d5743677c16e85c810e3024d54f0c8dea6424fad3c79ef6666e81dd0846f7437f5e729dfcdac8981bc9e5294c39b4580814d114076b8d36318f46ae4395 +"escape-string-regexp@npm:^5.0.0": + version: 5.0.0 + resolution: "escape-string-regexp@npm:5.0.0" + checksum: 20daabe197f3cb198ec28546deebcf24b3dbb1a5a269184381b3116d12f0532e06007f4bc8da25669d6a7f8efb68db0758df4cd981f57bc5b57f521a3e12c59e languageName: node linkType: hard "eslint-plugin-prettier@npm:^5.0.0": - version: 5.0.0 - resolution: "eslint-plugin-prettier@npm:5.0.0" + version: 5.0.1 + resolution: "eslint-plugin-prettier@npm:5.0.1" dependencies: prettier-linter-helpers: ^1.0.0 synckit: ^0.8.5 @@ -8746,7 +9571,7 @@ __metadata: optional: true eslint-config-prettier: optional: true - checksum: 84e88744b9050f2d5ef31b94e85294dda16f3a53c2449f9d33eac8ae6264889b459bf35a68e438fb6b329c2a1d6491aac4bfa00d86317e7009de3dad0311bec6 + checksum: c2261033b97bafe99ccb7cc47c2fac6fa85b8bbc8b128042e52631f906b69e12afed2cdd9d7e3021cc892ee8dd4204a3574e1f32a0b718b4bb3b440944b6983b languageName: node linkType: hard @@ -8778,16 +9603,17 @@ __metadata: linkType: hard "eslint@npm:^8.50.0": - version: 8.50.0 - resolution: "eslint@npm:8.50.0" + version: 8.55.0 + resolution: "eslint@npm:8.55.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 - "@eslint/eslintrc": ^2.1.2 - "@eslint/js": 8.50.0 - "@humanwhocodes/config-array": ^0.11.11 + "@eslint/eslintrc": ^2.1.4 + "@eslint/js": 8.55.0 + "@humanwhocodes/config-array": ^0.11.13 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 + "@ungap/structured-clone": ^1.2.0 ajv: ^6.12.4 chalk: ^4.0.0 cross-spawn: ^7.0.2 @@ -8820,7 +9646,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 9ebfe5615dc84700000d218e32ddfdcfc227ca600f65f18e5541ec34f8902a00356a9a8804d9468fd6c8637a5ef6a3897291dad91ba6579d5b32ffeae5e31768 + checksum: 83f82a604559dc1faae79d28fdf3dfc9e592ca221052e2ea516e1b379b37e77e4597705a16880e2f5ece4f79087c1dd13fd7f6e9746f794a401175519db18b41 languageName: node linkType: hard @@ -8877,6 +9703,65 @@ __metadata: languageName: node linkType: hard +"estree-util-attach-comments@npm:^3.0.0": + version: 3.0.0 + resolution: "estree-util-attach-comments@npm:3.0.0" + dependencies: + "@types/estree": ^1.0.0 + checksum: 56254eaef39659e6351919ebc2ae53a37a09290a14571c19e373e9d5fad343a3403d9ad0c23ae465d6e7d08c3e572fd56fb8c793efe6434a261bf1489932dbd5 + languageName: node + linkType: hard + +"estree-util-build-jsx@npm:^3.0.0": + version: 3.0.1 + resolution: "estree-util-build-jsx@npm:3.0.1" + dependencies: + "@types/estree-jsx": ^1.0.0 + devlop: ^1.0.0 + estree-util-is-identifier-name: ^3.0.0 + estree-walker: ^3.0.0 + checksum: 185eff060eda2ba32cecd15904db4f5ba0681159fbdf54f0f6586cd9411e77e733861a833d0aee3415e1d1fd4b17edf08bc9e9872cee98e6ec7b0800e1a85064 + languageName: node + linkType: hard + +"estree-util-is-identifier-name@npm:^3.0.0": + version: 3.0.0 + resolution: "estree-util-is-identifier-name@npm:3.0.0" + checksum: ea3909f0188ea164af0aadeca87c087e3e5da78d76da5ae9c7954ff1340ea3e4679c4653bbf4299ffb70caa9b322218cc1128db2541f3d2976eb9704f9857787 + languageName: node + linkType: hard + +"estree-util-to-js@npm:^2.0.0": + version: 2.0.0 + resolution: "estree-util-to-js@npm:2.0.0" + dependencies: + "@types/estree-jsx": ^1.0.0 + astring: ^1.8.0 + source-map: ^0.7.0 + checksum: 833edc94ab9978e0918f90261e0a3361bf4564fec4901f326d2237a9235d3f5fc6482da3be5acc545e702c8c7cb8bc5de5c7c71ba3b080eb1975bcfdf3923d79 + languageName: node + linkType: hard + +"estree-util-value-to-estree@npm:^3.0.1": + version: 3.0.1 + resolution: "estree-util-value-to-estree@npm:3.0.1" + dependencies: + "@types/estree": ^1.0.0 + is-plain-obj: ^4.0.0 + checksum: 7ab89084aa2c5677aeb0d7350ff21e71c9bbc424dc872a55bb4f25f63a7fd99fc7861626dd89b5544db3d3696212154bcf2b12b63ecd5a59dbfd07915c88aee4 + languageName: node + linkType: hard + +"estree-util-visit@npm:^2.0.0": + version: 2.0.0 + resolution: "estree-util-visit@npm:2.0.0" + dependencies: + "@types/estree-jsx": ^1.0.0 + "@types/unist": ^3.0.0 + checksum: 6444b38f224322945a6d19ea81a8828a0eec64aefb2bf1ea791fe20df496f7b7c543408d637df899e6a8e318b638f66226f16378a33c4c2b192ba5c3f891121f + languageName: node + linkType: hard + "estree-walker@npm:^1.0.1": version: 1.0.1 resolution: "estree-walker@npm:1.0.1" @@ -8884,14 +9769,23 @@ __metadata: languageName: node linkType: hard -"esutils@npm:^2.0.2, esutils@npm:^2.0.3": +"estree-walker@npm:^3.0.0": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": ^1.0.0 + checksum: a65728d5727b71de172c5df323385755a16c0fdab8234dc756c3854cfee343261ddfbb72a809a5660fac8c75d960bb3e21aa898c2d7e9b19bb298482ca58a3af + languageName: node + linkType: hard + +"esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" checksum: 22b5b08f74737379a840b8ed2036a5fb35826c709ab000683b092d9054e5c2a82c27818f12604bfc2a9a76b90b6834ef081edbc1c7ae30d1627012e067c6ec87 languageName: node linkType: hard -"eta@npm:^2.0.0": +"eta@npm:^2.0.0, eta@npm:^2.2.0": version: 2.2.0 resolution: "eta@npm:2.2.0" checksum: 6a09631481d4f26a9662a1eb736a65cc1cbc48e24935e6ff5d83a83b0cb509ea56d588d66d7c087d590601dc59bdabdac2356936b1b789d020eb0cf2d8304d54 @@ -9004,17 +9898,17 @@ __metadata: linkType: hard "ethers@npm:^6.7.1": - version: 6.7.1 - resolution: "ethers@npm:6.7.1" + version: 6.9.0 + resolution: "ethers@npm:6.9.0" dependencies: - "@adraffy/ens-normalize": 1.9.2 - "@noble/hashes": 1.1.2 - "@noble/secp256k1": 1.7.1 + "@adraffy/ens-normalize": 1.10.0 + "@noble/curves": 1.2.0 + "@noble/hashes": 1.3.2 "@types/node": 18.15.13 aes-js: 4.0.0-beta.5 tslib: 2.4.0 ws: 8.5.0 - checksum: 07833692e3f53b18e28c4cba9f53f3d5ebff8360de02ad57b2584c00c52b88f5b790373f9b9f6b4f6b52ffa2074530a6101192b30c3260f7cdeff929d34bb88b + checksum: e7b3b912b92b818fe65a192b32f4dd87ce0b71f4ffc194b4b3764b4b17d3b6ed953b667293e4c9276f785fa8c8659934c513843350317c61178af8e6165afbdd languageName: node linkType: hard @@ -9078,7 +9972,7 @@ __metadata: languageName: node linkType: hard -"execa@npm:^5.0.0": +"execa@npm:^5.0.0, execa@npm:^5.1.1": version: 5.1.1 resolution: "execa@npm:5.1.1" dependencies: @@ -9198,7 +10092,7 @@ __metadata: languageName: node linkType: hard -"fast-diff@npm:^1.1.2, fast-diff@npm:^1.2.0": +"fast-diff@npm:^1.1.2": version: 1.3.0 resolution: "fast-diff@npm:1.3.0" checksum: d22d371b994fdc8cce9ff510d7b8dc4da70ac327bcba20df607dd5b9cae9f908f4d1028f5fe467650f058d1e7270235ae0b8230809a262b4df587a3b3aa216c3 @@ -9206,15 +10100,15 @@ __metadata: linkType: hard "fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0": - version: 3.3.1 - resolution: "fast-glob@npm:3.3.1" + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" dependencies: "@nodelib/fs.stat": ^2.0.2 "@nodelib/fs.walk": ^1.2.3 glob-parent: ^5.1.2 merge2: ^1.3.0 micromatch: ^4.0.4 - checksum: b6f3add6403e02cf3a798bfbb1183d0f6da2afd368f27456010c0bc1f9640aea308243d4cb2c0ab142f618276e65ecb8be1661d7c62a7b4e5ba774b9ce5432e5 + checksum: 900e4979f4dbc3313840078419245621259f349950411ca2fa445a2f9a1a6d98c3b5e7e0660c5ccd563aa61abe133a21765c6c0dec8e57da1ba71d8000b05ec1 languageName: node linkType: hard @@ -9232,6 +10126,13 @@ __metadata: languageName: node linkType: hard +"fast-plist@npm:^0.1.2": + version: 0.1.3 + resolution: "fast-plist@npm:0.1.3" + checksum: e879f548db3a1fc89c654c476e9c9846f4335fdcd2283ec99e5f234c897f5616cee2a0a4201bf4b64ab6269e75c09daafc3933bd4a038c85af943fac0f113caa + languageName: node + linkType: hard + "fast-url-parser@npm:1.1.3": version: 1.1.3 resolution: "fast-url-parser@npm:1.1.3" @@ -9250,6 +10151,15 @@ __metadata: languageName: node linkType: hard +"fault@npm:^2.0.0": + version: 2.0.1 + resolution: "fault@npm:2.0.1" + dependencies: + format: ^0.2.0 + checksum: c9b30f47d95769177130a9409976a899ed31eb598450fbad5b0d39f2f5f56d5f4a9ff9257e0bee8407cb0fc3ce37165657888c6aa6d78472e403893104329b72 + languageName: node + linkType: hard + "faye-websocket@npm:^0.11.3": version: 0.11.4 resolution: "faye-websocket@npm:0.11.4" @@ -9259,37 +10169,6 @@ __metadata: languageName: node linkType: hard -"fbemitter@npm:^3.0.0": - version: 3.0.0 - resolution: "fbemitter@npm:3.0.0" - dependencies: - fbjs: ^3.0.0 - checksum: 069690b8cdff3521ade3c9beb92ba0a38d818a86ef36dff8690e66749aef58809db4ac0d6938eb1cacea2dbef5f2a508952d455669590264cdc146bbe839f605 - languageName: node - linkType: hard - -"fbjs-css-vars@npm:^1.0.0": - version: 1.0.2 - resolution: "fbjs-css-vars@npm:1.0.2" - checksum: 72baf6d22c45b75109118b4daecb6c8016d4c83c8c0f23f683f22e9d7c21f32fff6201d288df46eb561e3c7d4bb4489b8ad140b7f56444c453ba407e8bd28511 - languageName: node - linkType: hard - -"fbjs@npm:^3.0.0, fbjs@npm:^3.0.1": - version: 3.0.5 - resolution: "fbjs@npm:3.0.5" - dependencies: - cross-fetch: ^3.1.5 - fbjs-css-vars: ^1.0.0 - loose-envify: ^1.0.0 - object-assign: ^4.1.0 - promise: ^7.1.1 - setimmediate: ^1.0.5 - ua-parser-js: ^1.0.35 - checksum: e609b5b64686bc96495a5c67728ed9b2710b9b3d695c5759c5f5e47c9483d1c323543ac777a86459e3694efc5712c6ce7212e944feb19752867d699568bb0e54 - languageName: node - linkType: hard - "fd-slicer@npm:~1.1.0": version: 1.1.0 resolution: "fd-slicer@npm:1.1.0" @@ -9318,23 +10197,13 @@ __metadata: languageName: node linkType: hard -"fflate@npm:^0.8.0": +"fflate@npm:^0.8.0, fflate@npm:^0.8.1": version: 0.8.1 resolution: "fflate@npm:0.8.1" checksum: 7207e2d333243724485d2488095256b776184bd4545aa9967b655feaee5dc18e9525ed9b6d75f94cfd71d98fb285336f4902641683472f1d0c19a99137084cec languageName: node linkType: hard -"figures@npm:^5.0.0": - version: 5.0.0 - resolution: "figures@npm:5.0.0" - dependencies: - escape-string-regexp: ^5.0.0 - is-unicode-supported: ^1.2.0 - checksum: e6e8b6d1df2f554d4effae4a5ceff5d796f9449f6d4e912d74dab7d5f25916ecda6c305b9084833157d56485a0c78b37164430ddc5675bcee1330e346710669e - languageName: node - linkType: hard - "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -9398,6 +10267,16 @@ __metadata: languageName: node linkType: hard +"find-cache-dir@npm:^4.0.0": + version: 4.0.0 + resolution: "find-cache-dir@npm:4.0.0" + dependencies: + common-path-prefix: ^3.0.0 + pkg-dir: ^7.0.0 + checksum: 52a456a80deeb27daa3af6e06059b63bdb9cc4af4d845fc6d6229887e505ba913cd56000349caa60bc3aa59dacdb5b4c37903d4ba34c75102d83cab330b70d2f + languageName: node + linkType: hard + "find-replace@npm:^3.0.0": version: 3.0.0 resolution: "find-replace@npm:3.0.0" @@ -9445,7 +10324,7 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^6.0.0": +"find-up@npm:^6.3.0": version: 6.3.0 resolution: "find-up@npm:6.3.0" dependencies: @@ -9456,13 +10335,13 @@ __metadata: linkType: hard "flat-cache@npm:^3.0.4": - version: 3.1.0 - resolution: "flat-cache@npm:3.1.0" + version: 3.2.0 + resolution: "flat-cache@npm:3.2.0" dependencies: - flatted: ^3.2.7 + flatted: ^3.2.9 keyv: ^4.5.3 rimraf: ^3.0.2 - checksum: 99312601d5b90f44aef403f17f056dc09be7e437703740b166cdc9386d99e681f74e6b6e8bd7d010bda66904ea643c9527276b1b80308a2119741d94108a4d8f + checksum: e7e0f59801e288b54bee5cb9681e9ee21ee28ef309f886b312c9d08415b79fc0f24ac842f84356ce80f47d6a53de62197ce0e6e148dc42d5db005992e2a756ec languageName: node linkType: hard @@ -9475,25 +10354,13 @@ __metadata: languageName: node linkType: hard -"flatted@npm:^3.2.7": +"flatted@npm:^3.2.9": version: 3.2.9 resolution: "flatted@npm:3.2.9" checksum: f14167fbe26a9d20f6fca8d998e8f1f41df72c8e81f9f2c9d61ed2bea058248f5e1cbd05e7f88c0e5087a6a0b822a1e5e2b446e879f3cfbe0b07ba2d7f80b026 languageName: node linkType: hard -"flux@npm:^4.0.1": - version: 4.0.4 - resolution: "flux@npm:4.0.4" - dependencies: - fbemitter: ^3.0.0 - fbjs: ^3.0.1 - peerDependencies: - react: ^15.0.2 || ^16.0.0 || ^17.0.0 - checksum: 8fa5c2f9322258de3e331f67c6f1078a7f91c4dec9dbe8a54c4b8a80eed19a4f91889028b768668af4a796e8f2ee75e461e1571b8615432a3920ae95cc4ff794 - languageName: node - linkType: hard - "follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.12.1, follow-redirects@npm:^1.14.7, follow-redirects@npm:^1.15.0": version: 1.15.3 resolution: "follow-redirects@npm:1.15.3" @@ -9545,6 +10412,13 @@ __metadata: languageName: node linkType: hard +"form-data-encoder@npm:^2.1.2": + version: 2.1.4 + resolution: "form-data-encoder@npm:2.1.4" + checksum: e0b3e5950fb69b3f32c273944620f9861f1933df9d3e42066e038e26dfb343d0f4465de9f27e0ead1a09d9df20bc2eed06a63c2ca2f8f00949e7202bae9e29dd + languageName: node + linkType: hard + "form-data@npm:^4.0.0": version: 4.0.0 resolution: "form-data@npm:4.0.0" @@ -9556,6 +10430,13 @@ __metadata: languageName: node linkType: hard +"format@npm:^0.2.0": + version: 0.2.2 + resolution: "format@npm:0.2.2" + checksum: 646a60e1336250d802509cf24fb801e43bd4a70a07510c816fa133aa42cdbc9c21e66e9cc0801bb183c5b031c9d68be62e7fbb6877756e52357850f92aa28799 + languageName: node + linkType: hard + "formdata-polyfill@npm:^4.0.10": version: 4.0.10 resolution: "formdata-polyfill@npm:4.0.10" @@ -9638,6 +10519,17 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:^11.1.1": + version: 11.2.0 + resolution: "fs-extra@npm:11.2.0" + dependencies: + graceful-fs: ^4.2.0 + jsonfile: ^6.0.1 + universalify: ^2.0.0 + checksum: b12e42fa40ba47104202f57b8480dd098aa931c2724565e5e70779ab87605665594e76ee5fb00545f772ab9ace167fe06d2ab009c416dc8c842c5ae6df7aa7e8 + languageName: node + linkType: hard + "fs-extra@npm:^7.0.1": version: 7.0.1 resolution: "fs-extra@npm:7.0.1" @@ -9703,7 +10595,7 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:~2.3.2": +"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": version: 2.3.3 resolution: "fsevents@npm:2.3.3" dependencies: @@ -9722,7 +10614,7 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@~2.3.2#~builtin": +"fsevents@patch:fsevents@~2.3.2#~builtin, fsevents@patch:fsevents@~2.3.3#~builtin": version: 2.3.3 resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=df0bf1" dependencies: @@ -9731,10 +10623,10 @@ __metadata: languageName: node linkType: hard -"function-bind@npm:^1.1.1": - version: 1.1.1 - resolution: "function-bind@npm:1.1.1" - checksum: b32fbaebb3f8ec4969f033073b43f5c8befbb58f1a79e12f1d7490358150359ebd92f49e72ff0144f65f2c48ea2a605bff2d07965f548f6474fd8efd95bf361a +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 2b0ff4ce708d99715ad14a6d1f894e2a83242e4a52ccfcefaee5e40050562e5f6dafc1adbb4ce2d4ab47279a45dc736ab91ea5042d843c3c092820dfe032efb1 languageName: node linkType: hard @@ -9745,22 +10637,6 @@ __metadata: languageName: node linkType: hard -"gauge@npm:^4.0.3": - version: 4.0.4 - resolution: "gauge@npm:4.0.4" - dependencies: - aproba: ^1.0.3 || ^2.0.0 - color-support: ^1.1.3 - console-control-strings: ^1.1.0 - has-unicode: ^2.0.1 - signal-exit: ^3.0.7 - string-width: ^4.2.3 - strip-ansi: ^6.0.1 - wide-align: ^1.1.5 - checksum: 788b6bfe52f1dd8e263cda800c26ac0ca2ff6de0b6eee2fe0d9e3abf15e149b651bd27bf5226be10e6e3edb5c4e5d5985a5a1a98137e7a892f75eff76467ad2d - languageName: node - linkType: hard - "gensync@npm:^1.0.0-beta.1, gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -9775,22 +10651,22 @@ __metadata: languageName: node linkType: hard -"get-func-name@npm:^2.0.0": - version: 2.0.0 - resolution: "get-func-name@npm:2.0.0" - checksum: 8d82e69f3e7fab9e27c547945dfe5cc0c57fc0adf08ce135dddb01081d75684a03e7a0487466f478872b341d52ac763ae49e660d01ab83741f74932085f693c3 +"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2": + version: 2.0.2 + resolution: "get-func-name@npm:2.0.2" + checksum: 3f62f4c23647de9d46e6f76d2b3eafe58933a9b3830c60669e4180d6c601ce1b4aa310ba8366143f55e52b139f992087a9f0647274e8745621fa2af7e0acf13b languageName: node linkType: hard -"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1": - version: 1.2.1 - resolution: "get-intrinsic@npm:1.2.1" +"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2": + version: 1.2.2 + resolution: "get-intrinsic@npm:1.2.2" dependencies: - function-bind: ^1.1.1 - has: ^1.0.3 + function-bind: ^1.1.2 has-proto: ^1.0.1 has-symbols: ^1.0.3 - checksum: 5b61d88552c24b0cf6fa2d1b3bc5459d7306f699de060d76442cce49a4721f52b8c560a33ab392cf5575b7810277d54ded9d4d39a1ea61855619ebc005aa7e5f + hasown: ^2.0.0 + checksum: 447ff0724df26829908dc033b62732359596fcf66027bc131ab37984afb33842d9cd458fd6cecadfe7eac22fd8a54b349799ed334cf2726025c921c7250e7417 languageName: node linkType: hard @@ -9833,7 +10709,16 @@ __metadata: languageName: node linkType: hard -"github-slugger@npm:^1.4.0": +"get-tsconfig@npm:^4.7.2": + version: 4.7.2 + resolution: "get-tsconfig@npm:4.7.2" + dependencies: + resolve-pkg-maps: ^1.0.0 + checksum: 172358903250eff0103943f816e8a4e51d29b8e5449058bdf7266714a908a48239f6884308bd3a6ff28b09f692b9533dbebfd183ab63e4e14f073cda91f1bca9 + languageName: node + linkType: hard + +"github-slugger@npm:^1.4.0, github-slugger@npm:^1.5.0": version: 1.5.0 resolution: "github-slugger@npm:1.5.0" checksum: c70988224578b3bdaa25df65973ffc8c24594a77a28550c3636e495e49d17aef5cdb04c04fa3f1744babef98c61eecc6a43299a13ea7f3cc33d680bf9053ffbe @@ -9879,22 +10764,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2": - version: 10.3.5 - resolution: "glob@npm:10.3.5" - dependencies: - foreground-child: ^3.1.0 - jackspeak: ^2.0.3 - minimatch: ^9.0.1 - minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 - path-scurry: ^1.10.1 - bin: - glob: dist/cjs/src/bin.js - checksum: 564f4799cae48c0bcc841c88a20b539b5701c27ed5596f8623f588b3c523262d3fc20eb1ea89cab9c75b0912faf40ca5501fc835f982225d0d0599282b09e97a - languageName: node - linkType: hard - -"glob@npm:^10.3.10": +"glob@npm:^10.2.2, glob@npm:^10.3.10": version: 10.3.10 resolution: "glob@npm:10.3.10" dependencies: @@ -9909,7 +10779,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.0.0, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6": +"glob@npm:^7.0.0, glob@npm:^7.1.3, glob@npm:^7.1.6": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -9960,11 +10830,11 @@ __metadata: linkType: hard "globals@npm:^13.19.0": - version: 13.22.0 - resolution: "globals@npm:13.22.0" + version: 13.24.0 + resolution: "globals@npm:13.24.0" dependencies: type-fest: ^0.20.2 - checksum: 64af5a09565341432770444085f7aa98b54331c3b69732e0de411003921fa2dd060222ae7b50bec0b98f29c4d00b4f49bf434049ba9f7c36ca4ee1773f60458c + checksum: 56066ef058f6867c04ff203b8a44c15b038346a62efbc3060052a1016be9f56f4cf0b2cd45b74b22b81e521a889fc7786c73691b0549c2f3a6e825b3d394f43c languageName: node linkType: hard @@ -9982,7 +10852,7 @@ __metadata: languageName: node linkType: hard -"globby@npm:^13.1.1, globby@npm:^13.1.2, globby@npm:^13.1.4": +"globby@npm:^13.1.1, globby@npm:^13.1.2": version: 13.2.2 resolution: "globby@npm:13.2.2" dependencies: @@ -10004,6 +10874,25 @@ __metadata: languageName: node linkType: hard +"got@npm:^12.1.0": + version: 12.6.1 + resolution: "got@npm:12.6.1" + dependencies: + "@sindresorhus/is": ^5.2.0 + "@szmarczak/http-timer": ^5.0.1 + cacheable-lookup: ^7.0.0 + cacheable-request: ^10.2.8 + decompress-response: ^6.0.0 + form-data-encoder: ^2.1.2 + get-stream: ^6.0.1 + http2-wrapper: ^2.1.10 + lowercase-keys: ^3.0.0 + p-cancelable: ^3.0.0 + responselike: ^3.0.0 + checksum: 3c37f5d858aca2859f9932e7609d35881d07e7f2d44c039d189396f0656896af6c77c22f2c51c563f8918be483f60ff41e219de742ab4642d4b106711baccbd5 + languageName: node + linkType: hard + "got@npm:^9.6.0": version: 9.6.0 resolution: "got@npm:9.6.0" @@ -10023,6 +10912,13 @@ __metadata: languageName: node linkType: hard +"graceful-fs@npm:4.2.10": + version: 4.2.10 + resolution: "graceful-fs@npm:4.2.10" + checksum: 3f109d70ae123951905d85032ebeae3c2a5a7a997430df00ea30df0e3a6c60cf6689b109654d6fdacd28810a053348c4d14642da1d075049e6be1ba5216218da + languageName: node + linkType: hard + "graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.1.9, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" @@ -10066,8 +10962,8 @@ __metadata: linkType: hard "hardhat@npm:^2.17.4": - version: 2.17.4 - resolution: "hardhat@npm:2.17.4" + version: 2.19.2 + resolution: "hardhat@npm:2.19.2" dependencies: "@ethersproject/abi": ^5.1.2 "@metamask/eth-sig-util": ^4.0.0 @@ -10127,7 +11023,7 @@ __metadata: optional: true bin: hardhat: internal/cli/bootstrap.js - checksum: da8762f29ac08b6178edaedf1bf4641e8bcf44759c944906af644519fa9d0d3fb6c30e87add3904d8899f9cebfbde47a8422e219ad0bb24226c6636f2d3ef7c2 + checksum: 0b5499890e46750ca8c51bbe1205599b1424a2e5293b40c9f7cb56320d56b9935fbd4e276de370e07664ae81fa57dc7ab227bf2b2363f5732ef9f06df1a9a6d9 languageName: node linkType: hard @@ -10146,11 +11042,11 @@ __metadata: linkType: hard "has-property-descriptors@npm:^1.0.0": - version: 1.0.0 - resolution: "has-property-descriptors@npm:1.0.0" + version: 1.0.1 + resolution: "has-property-descriptors@npm:1.0.1" dependencies: - get-intrinsic: ^1.1.1 - checksum: a6d3f0a266d0294d972e354782e872e2fe1b6495b321e6ef678c9b7a06a40408a6891817350c62e752adced73a94ac903c54734fee05bf65b1905ee1368194bb + get-intrinsic: ^1.2.2 + checksum: 2bcc6bf6ec6af375add4e4b4ef586e43674850a91ad4d46666d0b28ba8e1fd69e424c7677d24d60f69470ad0afaa2f3197f508b20b0bb7dd99a8ab77ffc4b7c4 languageName: node linkType: hard @@ -10177,13 +11073,6 @@ __metadata: languageName: node linkType: hard -"has-unicode@npm:^2.0.1": - version: 2.0.1 - resolution: "has-unicode@npm:2.0.1" - checksum: 1eab07a7436512db0be40a710b29b5dc21fa04880b7f63c9980b706683127e3c1b57cb80ea96d47991bdae2dfe479604f6a1ba410106ee1046a41d1bd0814400 - languageName: node - linkType: hard - "has-yarn@npm:^2.1.0": version: 2.1.0 resolution: "has-yarn@npm:2.1.0" @@ -10191,12 +11080,10 @@ __metadata: languageName: node linkType: hard -"has@npm:^1.0.3": - version: 1.0.3 - resolution: "has@npm:1.0.3" - dependencies: - function-bind: ^1.1.1 - checksum: b9ad53d53be4af90ce5d1c38331e712522417d017d5ef1ebd0507e07c2fbad8686fffb8e12ddecd4c39ca9b9b47431afbb975b8abf7f3c3b82c98e9aad052792 +"has-yarn@npm:^3.0.0": + version: 3.0.0 + resolution: "has-yarn@npm:3.0.0" + checksum: b9e14e78e0a37bc070550c862b201534287bc10e62a86ec9c1f455ffb082db42817ce9aed914bd73f1d589bbf268520e194629ff2f62ff6b98a482c4bd2dcbfb languageName: node linkType: hard @@ -10221,6 +11108,15 @@ __metadata: languageName: node linkType: hard +"hasown@npm:^2.0.0": + version: 2.0.0 + resolution: "hasown@npm:2.0.0" + dependencies: + function-bind: ^1.1.2 + checksum: 6151c75ca12554565098641c98a40f4cc86b85b0fd5b6fe92360967e4605a4f9610f7757260b4e8098dd1c2ce7f4b095f2006fe72a570e3b6d2d28de0298c176 + languageName: node + linkType: hard + "hast-to-hyperscript@npm:^9.0.0": version: 9.0.1 resolution: "hast-to-hyperscript@npm:9.0.1" @@ -10236,6 +11132,43 @@ __metadata: languageName: node linkType: hard +"hast-util-from-dom@npm:^5.0.0": + version: 5.0.0 + resolution: "hast-util-from-dom@npm:5.0.0" + dependencies: + "@types/hast": ^3.0.0 + hastscript: ^8.0.0 + web-namespaces: ^2.0.0 + checksum: bf8f96c480a598b42156227be2210bbb7a08da519ae4d57814385c8560b01e2b6b5fbde2afce808ce7ba7c5cd172822d4285b8f5edde2d13089bc9c3177c0d09 + languageName: node + linkType: hard + +"hast-util-from-html-isomorphic@npm:^2.0.0": + version: 2.0.0 + resolution: "hast-util-from-html-isomorphic@npm:2.0.0" + dependencies: + "@types/hast": ^3.0.0 + hast-util-from-dom: ^5.0.0 + hast-util-from-html: ^2.0.0 + unist-util-remove-position: ^5.0.0 + checksum: a98d02890bd1b5a804a1b2aaacd0332a6563f2a8df620450e38ab8962728cda0485cd29435824840621d1e653943776864e912d78d24cce6a7f484011ee7cef0 + languageName: node + linkType: hard + +"hast-util-from-html@npm:^2.0.0": + version: 2.0.1 + resolution: "hast-util-from-html@npm:2.0.1" + dependencies: + "@types/hast": ^3.0.0 + devlop: ^1.1.0 + hast-util-from-parse5: ^8.0.0 + parse5: ^7.0.0 + vfile: ^6.0.0 + vfile-message: ^4.0.0 + checksum: 8decdec1f2750d3d8d4933a4d06d78846a9fb3c97cded07395d160adae22bacfc69eaf113fd95a6ad696d1e5877580f2ac83a4161fa9f3becb0fafe2cec8b0ea + languageName: node + linkType: hard + "hast-util-from-parse5@npm:^6.0.0": version: 6.0.1 resolution: "hast-util-from-parse5@npm:6.0.1" @@ -10250,13 +11183,38 @@ __metadata: languageName: node linkType: hard -"hast-util-is-element@npm:^1.0.0, hast-util-is-element@npm:^1.1.0": +"hast-util-from-parse5@npm:^8.0.0": + version: 8.0.1 + resolution: "hast-util-from-parse5@npm:8.0.1" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + devlop: ^1.0.0 + hastscript: ^8.0.0 + property-information: ^6.0.0 + vfile: ^6.0.0 + vfile-location: ^5.0.0 + web-namespaces: ^2.0.0 + checksum: fdd1ab8b03af13778ecb94ef9a58b1e3528410cdfceb3d6bb7600508967d0d836b451bc7bc3baf66efb7c730d3d395eea4bb1b30352b0162823d9f0de976774b + languageName: node + linkType: hard + +"hast-util-is-element@npm:^1.1.0": version: 1.1.0 resolution: "hast-util-is-element@npm:1.1.0" checksum: 30fad3f65e7ab2f0efd5db9e7344d0820b70971988dfe79f62d8447598b2a1ce8a59cd4bfc05ae0d9a1c451b9b53cbe1023743d7eac764d64720b6b73475f62f languageName: node linkType: hard +"hast-util-is-element@npm:^3.0.0": + version: 3.0.0 + resolution: "hast-util-is-element@npm:3.0.0" + dependencies: + "@types/hast": ^3.0.0 + checksum: 82569a420eda5877c52fdbbdbe26675f012c02d70813dfd19acffdee328e42e4bd0b7ae34454cfcbcb932b2bedbd7ddc119f943a0cfb234120f9456d6c0c4331 + languageName: node + linkType: hard + "hast-util-parse-selector@npm:^2.0.0": version: 2.2.5 resolution: "hast-util-parse-selector@npm:2.2.5" @@ -10264,6 +11222,15 @@ __metadata: languageName: node linkType: hard +"hast-util-parse-selector@npm:^4.0.0": + version: 4.0.0 + resolution: "hast-util-parse-selector@npm:4.0.0" + dependencies: + "@types/hast": ^3.0.0 + checksum: 76087670d3b0b50b23a6cb70bca53a6176d6608307ccdbb3ed18b650b82e7c3513bfc40348f1389dc0c5ae872b9a768851f4335f44654abd7deafd6974c52402 + languageName: node + linkType: hard + "hast-util-raw@npm:6.0.1": version: 6.0.1 resolution: "hast-util-raw@npm:6.0.1" @@ -10282,27 +11249,120 @@ __metadata: languageName: node linkType: hard -"hast-util-to-parse5@npm:^6.0.0": - version: 6.0.0 - resolution: "hast-util-to-parse5@npm:6.0.0" - dependencies: - hast-to-hyperscript: ^9.0.0 - property-information: ^5.0.0 - web-namespaces: ^1.0.0 +"hast-util-raw@npm:^9.0.0": + version: 9.0.1 + resolution: "hast-util-raw@npm:9.0.1" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + "@ungap/structured-clone": ^1.0.0 + hast-util-from-parse5: ^8.0.0 + hast-util-to-parse5: ^8.0.0 + html-void-elements: ^3.0.0 + mdast-util-to-hast: ^13.0.0 + parse5: ^7.0.0 + unist-util-position: ^5.0.0 + unist-util-visit: ^5.0.0 + vfile: ^6.0.0 + web-namespaces: ^2.0.0 + zwitch: ^2.0.0 + checksum: 4b486eb4782eafb471ae639d45c14ac8797676518cf5da16adc973f52d7b8e1075a1451558c023b390820bd9fd213213e6248a2dae71b68ac5040b277509b8d9 + languageName: node + linkType: hard + +"hast-util-to-estree@npm:^3.0.0": + version: 3.1.0 + resolution: "hast-util-to-estree@npm:3.1.0" + dependencies: + "@types/estree": ^1.0.0 + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + comma-separated-tokens: ^2.0.0 + devlop: ^1.0.0 + estree-util-attach-comments: ^3.0.0 + estree-util-is-identifier-name: ^3.0.0 + hast-util-whitespace: ^3.0.0 + mdast-util-mdx-expression: ^2.0.0 + mdast-util-mdx-jsx: ^3.0.0 + mdast-util-mdxjs-esm: ^2.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + style-to-object: ^0.4.0 + unist-util-position: ^5.0.0 + zwitch: ^2.0.0 + checksum: 61272f7c18c9d2a5e34df7cfd2c97cbf12f6e9d05114d60e4dedd64e5576565eb1e35c78b9213c909bb8f984f0f8e9c49b568f04bdb444b83d0bca9159e14f3c + languageName: node + linkType: hard + +"hast-util-to-jsx-runtime@npm:^2.0.0": + version: 2.3.0 + resolution: "hast-util-to-jsx-runtime@npm:2.3.0" + dependencies: + "@types/estree": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + comma-separated-tokens: ^2.0.0 + devlop: ^1.0.0 + estree-util-is-identifier-name: ^3.0.0 + hast-util-whitespace: ^3.0.0 + mdast-util-mdx-expression: ^2.0.0 + mdast-util-mdx-jsx: ^3.0.0 + mdast-util-mdxjs-esm: ^2.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + style-to-object: ^1.0.0 + unist-util-position: ^5.0.0 + vfile-message: ^4.0.0 + checksum: 599a97c6ec61c1430776813d7fb42e6f96032bf4a04dfcbb8eceef3bc8d1845ecf242387a4426b9d3f52320dbbfa26450643b81124b3d6a0b9bbb0fff4d0ba83 + languageName: node + linkType: hard + +"hast-util-to-parse5@npm:^6.0.0": + version: 6.0.0 + resolution: "hast-util-to-parse5@npm:6.0.0" + dependencies: + hast-to-hyperscript: ^9.0.0 + property-information: ^5.0.0 + web-namespaces: ^1.0.0 xtend: ^4.0.0 zwitch: ^1.0.0 checksum: 91a36244e37df1d63c8b7e865ab0c0a25bb7396155602be005cf71d95c348e709568f80e0f891681a3711d733ad896e70642dc41a05b574eddf2e07d285408a8 languageName: node linkType: hard -"hast-util-to-text@npm:^2.0.0": - version: 2.0.1 - resolution: "hast-util-to-text@npm:2.0.1" +"hast-util-to-parse5@npm:^8.0.0": + version: 8.0.0 + resolution: "hast-util-to-parse5@npm:8.0.0" + dependencies: + "@types/hast": ^3.0.0 + comma-separated-tokens: ^2.0.0 + devlop: ^1.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + web-namespaces: ^2.0.0 + zwitch: ^2.0.0 + checksum: 137469209cb2b32b57387928878dc85310fbd5afa4807a8da69529199bb1d19044bfc95b50c3dc68d4fb2b6cb8bf99b899285597ab6ab318f50422eefd5599dd + languageName: node + linkType: hard + +"hast-util-to-text@npm:^4.0.0": + version: 4.0.0 + resolution: "hast-util-to-text@npm:4.0.0" + dependencies: + "@types/hast": ^3.0.0 + "@types/unist": ^3.0.0 + hast-util-is-element: ^3.0.0 + unist-util-find-after: ^5.0.0 + checksum: 3beedbdf20e2ecc9352cdd0963848b741294c1f3872d43400125bc0ca2d7938d5358081b0f9c252ec15c22368f30a4e7e6ca0ce5a57d4d2bcdd02adbf884e2af + languageName: node + linkType: hard + +"hast-util-whitespace@npm:^3.0.0": + version: 3.0.0 + resolution: "hast-util-whitespace@npm:3.0.0" dependencies: - hast-util-is-element: ^1.0.0 - repeat-string: ^1.0.0 - unist-util-find-after: ^3.0.0 - checksum: 4e7960b414b7a6b2f0180e4af416cd8ae3c7ba1531d7eaec7e6dc9509daf88308784bbf5b94885384dccc42abcb74cc6cc26755c76914d646f32aa6bc32ea34b + "@types/hast": ^3.0.0 + checksum: 41d93ccce218ba935dc3c12acdf586193c35069489c8c8f50c2aa824c00dec94a3c78b03d1db40fa75381942a189161922e4b7bca700b3a2cc779634c351a1e4 languageName: node linkType: hard @@ -10319,6 +11379,19 @@ __metadata: languageName: node linkType: hard +"hastscript@npm:^8.0.0": + version: 8.0.0 + resolution: "hastscript@npm:8.0.0" + dependencies: + "@types/hast": ^3.0.0 + comma-separated-tokens: ^2.0.0 + hast-util-parse-selector: ^4.0.0 + property-information: ^6.0.0 + space-separated-tokens: ^2.0.0 + checksum: ae3c20223e7b847320c0f98b6fb3c763ebe1bf3913c5805fbc176cf84553a9db1117ca34cf842a5235890b4b9ae0e94501bfdc9a9b870a5dbf5fc52426db1097 + languageName: node + linkType: hard + "he@npm:1.2.0, he@npm:^1.2.0": version: 1.2.0 resolution: "he@npm:1.2.0" @@ -10381,7 +11454,7 @@ __metadata: languageName: node linkType: hard -"html-escaper@npm:^2.0.0": +"html-escaper@npm:^2.0.0, html-escaper@npm:^2.0.2": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" checksum: d2df2da3ad40ca9ee3a39c5cc6475ef67c8f83c234475f24d8e9ce0dc80a2c82df8e1d6fa78ddd1e9022a586ea1bd247a615e80a5cd9273d90111ddda7d9e974 @@ -10405,7 +11478,24 @@ __metadata: languageName: node linkType: hard -"html-tags@npm:^3.2.0": +"html-minifier-terser@npm:^7.2.0": + version: 7.2.0 + resolution: "html-minifier-terser@npm:7.2.0" + dependencies: + camel-case: ^4.1.2 + clean-css: ~5.3.2 + commander: ^10.0.0 + entities: ^4.4.0 + param-case: ^3.0.4 + relateurl: ^0.2.7 + terser: ^5.15.1 + bin: + html-minifier-terser: cli.js + checksum: 39feed354b5a8aafc8e910977d68cfd961d6db330a8e1a5b16a528c86b8ee7745d8945134822cf00acf7bf0d0135bf1abad650bf308bee4ea73adb003f5b8656 + languageName: node + linkType: hard + +"html-tags@npm:^3.2.0, html-tags@npm:^3.3.1": version: 3.3.1 resolution: "html-tags@npm:3.3.1" checksum: b4ef1d5a76b678e43cce46e3783d563607b1d550cab30b4f511211564574770aa8c658a400b100e588bc60b8234e59b35ff72c7851cc28f3b5403b13a2c6cbce @@ -10419,9 +11509,16 @@ __metadata: languageName: node linkType: hard -"html-webpack-plugin@npm:^5.5.0": - version: 5.5.3 - resolution: "html-webpack-plugin@npm:5.5.3" +"html-void-elements@npm:^3.0.0": + version: 3.0.0 + resolution: "html-void-elements@npm:3.0.0" + checksum: 59be397525465a7489028afa064c55763d9cccd1d7d9f630cca47137317f0e897a9ca26cef7e745e7cff1abc44260cfa407742b243a54261dfacd42230e94fce + languageName: node + linkType: hard + +"html-webpack-plugin@npm:^5.5.0, html-webpack-plugin@npm:^5.5.3": + version: 5.5.4 + resolution: "html-webpack-plugin@npm:5.5.4" dependencies: "@types/html-minifier-terser": ^6.0.0 html-minifier-terser: ^6.0.2 @@ -10430,7 +11527,7 @@ __metadata: tapable: ^2.0.0 peerDependencies: webpack: ^5.20.0 - checksum: ccf685195739c372ad641bbd0c9100a847904f34eedc7aff3ece7856cd6c78fd3746d2d615af1bb71e5727993fe711b89e9b744f033ed3fde646540bf5d5e954 + checksum: b49befb73d67a3716fd0e6f7776b108d2b0b7050fb8221f05cd114cbae13c03150a13b7cdf5e76170be040ce7936a1cf76f7a4bfd9ebe1552b72d7889a74c374 languageName: node linkType: hard @@ -10527,14 +11624,13 @@ __metadata: languageName: node linkType: hard -"http-proxy-agent@npm:^5.0.0": - version: 5.0.0 - resolution: "http-proxy-agent@npm:5.0.0" +"http-proxy-agent@npm:^7.0.0": + version: 7.0.0 + resolution: "http-proxy-agent@npm:7.0.0" dependencies: - "@tootallnate/once": 2 - agent-base: 6 - debug: 4 - checksum: e2ee1ff1656a131953839b2a19cd1f3a52d97c25ba87bd2559af6ae87114abf60971e498021f9b73f9fd78aea8876d1fb0d4656aac8a03c6caa9fc175f22b786 + agent-base: ^7.1.0 + debug: ^4.3.4 + checksum: 48d4fac997917e15f45094852b63b62a46d0c8a4f0b9c6c23ca26d27b8df8d178bed88389e604745e748bd9a01f5023e25093722777f0593c3f052009ff438b6 languageName: node linkType: hard @@ -10567,6 +11663,16 @@ __metadata: languageName: node linkType: hard +"http2-wrapper@npm:^2.1.10": + version: 2.2.1 + resolution: "http2-wrapper@npm:2.2.1" + dependencies: + quick-lru: ^5.1.1 + resolve-alpn: ^1.2.0 + checksum: e95e55e22c6fd61182ce81fecb9b7da3af680d479febe8ad870d05f7ebbc9f076e455193766f4e7934e50913bf1d8da3ba121fb5cd2928892390b58cf9d5c509 + languageName: node + linkType: hard + "https-proxy-agent@npm:5.0.1, https-proxy-agent@npm:^5.0.0": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" @@ -10577,6 +11683,16 @@ __metadata: languageName: node linkType: hard +"https-proxy-agent@npm:^7.0.1": + version: 7.0.2 + resolution: "https-proxy-agent@npm:7.0.2" + dependencies: + agent-base: ^7.0.2 + debug: 4 + checksum: 088969a0dd476ea7a0ed0a2cf1283013682b08f874c3bc6696c83fa061d2c157d29ef0ad3eb70a2046010bb7665573b2388d10fdcb3e410a66995e5248444292 + languageName: node + linkType: hard + "human-signals@npm:^2.1.0": version: 2.1.0 resolution: "human-signals@npm:2.1.0" @@ -10591,15 +11707,6 @@ __metadata: languageName: node linkType: hard -"humanize-ms@npm:^1.2.1": - version: 1.2.1 - resolution: "humanize-ms@npm:1.2.1" - dependencies: - ms: ^2.0.0 - checksum: 9c7a74a2827f9294c009266c82031030eae811ca87b0da3dceb8d6071b9bde22c9f3daef0469c3c533cc67a97d8a167cd9fc0389350e5f415f61a79b171ded16 - languageName: node - linkType: hard - "iconv-lite@npm:0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" @@ -10634,21 +11741,14 @@ __metadata: languageName: node linkType: hard -"ignore-by-default@npm:^2.1.0": - version: 2.1.0 - resolution: "ignore-by-default@npm:2.1.0" - checksum: 2b2df4622b6a07a3e91893987be8f060dc553f7736b67e72aa2312041c450a6fa8371733d03c42f45a02e47ec824e961c2fba63a3d94fc59cbd669220a5b0d7a - languageName: node - linkType: hard - "ignore@npm:^5.2.0, ignore@npm:^5.2.4": - version: 5.2.4 - resolution: "ignore@npm:5.2.4" - checksum: 3d4c309c6006e2621659311783eaea7ebcd41fe4ca1d78c91c473157ad6666a57a2df790fe0d07a12300d9aac2888204d7be8d59f9aaf665b1c7fcdb432517ef + version: 5.3.0 + resolution: "ignore@npm:5.3.0" + checksum: 2736da6621f14ced652785cb05d86301a66d70248597537176612bd0c8630893564bd5f6421f8806b09e8472e75c591ef01672ab8059c07c6eb2c09cefe04bf9 languageName: node linkType: hard -"image-size@npm:^1.0.1": +"image-size@npm:^1.0.1, image-size@npm:^1.0.2": version: 1.0.2 resolution: "image-size@npm:1.0.2" dependencies: @@ -10697,6 +11797,13 @@ __metadata: languageName: node linkType: hard +"import-lazy@npm:^4.0.0": + version: 4.0.0 + resolution: "import-lazy@npm:4.0.0" + checksum: 22f5e51702134aef78890156738454f620e5fe7044b204ebc057c614888a1dd6fdf2ede0fdcca44d5c173fd64f65c985f19a51775b06967ef58cc3d26898df07 + languageName: node + linkType: hard + "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -10711,13 +11818,6 @@ __metadata: languageName: node linkType: hard -"indent-string@npm:^5.0.0": - version: 5.0.0 - resolution: "indent-string@npm:5.0.0" - checksum: e466c27b6373440e6d84fbc19e750219ce25865cb82d578e41a6053d727e5520dc5725217d6eb1cc76005a1bb1696a0f106d84ce7ebda3033b963a38583fb3b3 - languageName: node - linkType: hard - "infima@npm:0.2.0-alpha.43": version: 0.2.0-alpha.43 resolution: "infima@npm:0.2.0-alpha.43" @@ -10726,9 +11826,9 @@ __metadata: linkType: hard "inflation@npm:^2.0.0": - version: 2.0.0 - resolution: "inflation@npm:2.0.0" - checksum: a0494871b12275afdef9e2710ee1af1e0fc642b04613a9be69c05ef8b5e9627f3bd7d358a937fa47aa20235ee7313a4f30255048533add0ad4918beb918a586e + version: 2.1.0 + resolution: "inflation@npm:2.1.0" + checksum: 80c1b5d9ec408105a85f0623c824d668ddf0cadafd8d9716c0737990e5a712ae5f7d6bb0ff216b6648eccb9c6ac69fe06c0d8c58456d168db5bf550c89dd74ed languageName: node linkType: hard @@ -10763,7 +11863,7 @@ __metadata: languageName: node linkType: hard -"ini@npm:^1.3.5, ini@npm:~1.3.0": +"ini@npm:^1.3.4, ini@npm:^1.3.5, ini@npm:~1.3.0": version: 1.3.8 resolution: "ini@npm:1.3.8" checksum: dfd98b0ca3a4fc1e323e38a6c8eb8936e31a97a918d3b377649ea15bdb15d481207a0dda1021efbd86b464cae29a0d33c1d7dcaf6c5672bee17fa849bc50a1b3 @@ -10777,6 +11877,13 @@ __metadata: languageName: node linkType: hard +"inline-style-parser@npm:0.2.2": + version: 0.2.2 + resolution: "inline-style-parser@npm:0.2.2" + checksum: 698893d6542d4e7c0377936a1c7daec34a197765bd77c5599384756a95ce8804e6b79347b783aa591d5e9c6f3d33dae74c6d4cad3a94647eb05f3a785e927a3f + languageName: node + linkType: hard + "integration-tests@workspace:compiler/integration-tests": version: 0.0.0-use.local resolution: "integration-tests@workspace:compiler/integration-tests" @@ -10784,7 +11891,6 @@ __metadata: "@noir-lang/backend_barretenberg": "workspace:*" "@noir-lang/noir_js": "workspace:*" "@noir-lang/noir_wasm": "workspace:*" - "@noir-lang/source-resolver": "workspace:*" "@nomicfoundation/hardhat-chai-matchers": ^2.0.0 "@nomicfoundation/hardhat-ethers": ^3.0.0 "@web/dev-server-esbuild": ^0.3.6 @@ -10854,13 +11960,6 @@ __metadata: languageName: node linkType: hard -"irregular-plurals@npm:^3.3.0": - version: 3.5.0 - resolution: "irregular-plurals@npm:3.5.0" - checksum: 5b663091dc89155df7b2e9d053e8fb11941a0c4be95c4b6549ed3ea020489fdf4f75ea586c915b5b543704252679a5a6e8c6c3587da5ac3fc57b12da90a9aee7 - languageName: node - linkType: hard - "is-alphabetical@npm:1.0.4, is-alphabetical@npm:^1.0.0": version: 1.0.4 resolution: "is-alphabetical@npm:1.0.4" @@ -10868,6 +11967,13 @@ __metadata: languageName: node linkType: hard +"is-alphabetical@npm:^2.0.0": + version: 2.0.1 + resolution: "is-alphabetical@npm:2.0.1" + checksum: 56207db8d9de0850f0cd30f4966bf731eb82cedfe496cbc2e97e7c3bacaf66fc54a972d2d08c0d93bb679cb84976a05d24c5ad63de56fabbfc60aadae312edaa + languageName: node + linkType: hard + "is-alphanumerical@npm:^1.0.0": version: 1.0.4 resolution: "is-alphanumerical@npm:1.0.4" @@ -10878,6 +11984,16 @@ __metadata: languageName: node linkType: hard +"is-alphanumerical@npm:^2.0.0": + version: 2.0.1 + resolution: "is-alphanumerical@npm:2.0.1" + dependencies: + is-alphabetical: ^2.0.0 + is-decimal: ^2.0.0 + checksum: 87acc068008d4c9c4e9f5bd5e251041d42e7a50995c77b1499cf6ed248f971aadeddb11f239cabf09f7975ee58cac7a48ffc170b7890076d8d227b24a68663c9 + languageName: node + linkType: hard + "is-arrayish@npm:^0.2.1": version: 0.2.1 resolution: "is-arrayish@npm:0.2.1" @@ -10921,12 +12037,23 @@ __metadata: languageName: node linkType: hard +"is-ci@npm:^3.0.1": + version: 3.0.1 + resolution: "is-ci@npm:3.0.1" + dependencies: + ci-info: ^3.2.0 + bin: + is-ci: bin.js + checksum: 192c66dc7826d58f803ecae624860dccf1899fc1f3ac5505284c0a5cf5f889046ffeb958fa651e5725d5705c5bcb14f055b79150ea5fcad7456a9569de60260e + languageName: node + linkType: hard + "is-core-module@npm:^2.13.0": - version: 2.13.0 - resolution: "is-core-module@npm:2.13.0" + version: 2.13.1 + resolution: "is-core-module@npm:2.13.1" dependencies: - has: ^1.0.3 - checksum: 053ab101fb390bfeb2333360fd131387bed54e476b26860dc7f5a700bbf34a0ec4454f7c8c4d43e8a0030957e4b3db6e16d35e1890ea6fb654c833095e040355 + hasown: ^2.0.0 + checksum: 256559ee8a9488af90e4bad16f5583c6d59e92f0742e9e8bb4331e758521ee86b810b93bae44f390766ffbc518a0488b18d9dab7da9a5ff997d499efc9403f7c languageName: node linkType: hard @@ -10937,6 +12064,13 @@ __metadata: languageName: node linkType: hard +"is-decimal@npm:^2.0.0": + version: 2.0.1 + resolution: "is-decimal@npm:2.0.1" + checksum: 97132de7acdce77caa7b797632970a2ecd649a88e715db0e4dbc00ab0708b5e7574ba5903962c860cd4894a14fd12b100c0c4ac8aed445cf6f55c6cf747a4158 + languageName: node + linkType: hard + "is-docker@npm:^2.0.0, is-docker@npm:^2.1.1": version: 2.2.1 resolution: "is-docker@npm:2.2.1" @@ -10955,13 +12089,6 @@ __metadata: languageName: node linkType: hard -"is-error@npm:^2.2.2": - version: 2.2.2 - resolution: "is-error@npm:2.2.2" - checksum: a97b39587150f0d38f9f93f64699807fe3020fe5edbd63548f234dc2ba96fd7c776d66c062bf031dfeb93c7f48db563ff6bde588418ca041da37c659a416f055 - languageName: node - linkType: hard - "is-extendable@npm:^0.1.0": version: 0.1.1 resolution: "is-extendable@npm:0.1.1" @@ -10983,13 +12110,6 @@ __metadata: languageName: node linkType: hard -"is-fullwidth-code-point@npm:^4.0.0": - version: 4.0.0 - resolution: "is-fullwidth-code-point@npm:4.0.0" - checksum: 8ae89bf5057bdf4f57b346fb6c55e9c3dd2549983d54191d722d5c739397a903012cc41a04ee3403fd872e811243ef91a7c5196da7b5841dc6b6aae31a264a8d - languageName: node - linkType: hard - "is-generator-function@npm:^1.0.7": version: 1.0.10 resolution: "is-generator-function@npm:1.0.10" @@ -11022,6 +12142,13 @@ __metadata: languageName: node linkType: hard +"is-hexadecimal@npm:^2.0.0": + version: 2.0.1 + resolution: "is-hexadecimal@npm:2.0.1" + checksum: 66a2ea85994c622858f063f23eda506db29d92b52580709eb6f4c19550552d4dcf3fb81952e52f7cf972097237959e00adc7bb8c9400cd12886e15bf06145321 + languageName: node + linkType: hard + "is-inside-container@npm:^1.0.0": version: 1.0.0 resolution: "is-inside-container@npm:1.0.0" @@ -11064,6 +12191,13 @@ __metadata: languageName: node linkType: hard +"is-npm@npm:^6.0.0": + version: 6.0.0 + resolution: "is-npm@npm:6.0.0" + checksum: fafe1ddc772345f5460514891bb8014376904ccdbddd59eee7525c9adcc08d426933f28b087bef3e17524da7ebf35c03ef484ff3b6ba9d5fecd8c6e6a7d4bf11 + languageName: node + linkType: hard + "is-number@npm:^7.0.0": version: 7.0.0 resolution: "is-number@npm:7.0.0" @@ -11113,6 +12247,13 @@ __metadata: languageName: node linkType: hard +"is-plain-obj@npm:^4.0.0": + version: 4.1.0 + resolution: "is-plain-obj@npm:4.1.0" + checksum: 6dc45da70d04a81f35c9310971e78a6a3c7a63547ef782e3a07ee3674695081b6ca4e977fbb8efc48dae3375e0b34558d2bcd722aec9bddfa2d7db5b041be8ce + languageName: node + linkType: hard + "is-plain-object@npm:^2.0.4": version: 2.0.4 resolution: "is-plain-object@npm:2.0.4" @@ -11129,10 +12270,19 @@ __metadata: languageName: node linkType: hard -"is-promise@npm:^4.0.0": +"is-port-reachable@npm:4.0.0": version: 4.0.0 - resolution: "is-promise@npm:4.0.0" - checksum: 0b46517ad47b00b6358fd6553c83ec1f6ba9acd7ffb3d30a0bf519c5c69e7147c132430452351b8a9fc198f8dd6c4f76f8e6f5a7f100f8c77d57d9e0f4261a8a + resolution: "is-port-reachable@npm:4.0.0" + checksum: 47b7e10db8edcef27fbf9e50f0de85ad368d35688790ca64a13db67260111ac5f4b98989b11af06199fa93f25d810bd09a5b21b2c2646529668638f7c34d3c04 + languageName: node + linkType: hard + +"is-reference@npm:^3.0.0": + version: 3.0.2 + resolution: "is-reference@npm:3.0.2" + dependencies: + "@types/estree": "*" + checksum: ac3bf5626fe9d0afbd7454760d73c47f16b9f471401b9749721ad3b66f0a39644390382acf88ca9d029c95782c1e2ec65662855e3ba91acf52d82231247a7fd3 languageName: node linkType: hard @@ -11178,13 +12328,6 @@ __metadata: languageName: node linkType: hard -"is-unicode-supported@npm:^1.2.0": - version: 1.3.0 - resolution: "is-unicode-supported@npm:1.3.0" - checksum: 20a1fc161afafaf49243551a5ac33b6c4cf0bbcce369fcd8f2951fbdd000c30698ce320de3ee6830497310a8f41880f8066d440aa3eb0a853e2aa4836dd89abc - languageName: node - linkType: hard - "is-whitespace-character@npm:^1.0.0": version: 1.0.4 resolution: "is-whitespace-character@npm:1.0.4" @@ -11215,6 +12358,13 @@ __metadata: languageName: node linkType: hard +"is-yarn-global@npm:^0.4.0": + version: 0.4.1 + resolution: "is-yarn-global@npm:0.4.1" + checksum: 79ec4e6f581c53d4fefdf5f6c237f9a3ad8db29c85cdc4659e76ae345659317552052a97b7e56952aa5d94a23c798ebec8ccad72fb14d3b26dc647ddceddd716 + languageName: node + linkType: hard + "isarray@npm:0.0.1": version: 0.0.1 resolution: "isarray@npm:0.0.1" @@ -11243,6 +12393,13 @@ __metadata: languageName: node linkType: hard +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e + languageName: node + linkType: hard + "isobject@npm:^3.0.1": version: 3.0.1 resolution: "isobject@npm:3.0.1" @@ -11251,9 +12408,9 @@ __metadata: linkType: hard "istanbul-lib-coverage@npm:^3.0.0": - version: 3.2.0 - resolution: "istanbul-lib-coverage@npm:3.2.0" - checksum: a2a545033b9d56da04a8571ed05c8120bf10e9bce01cf8633a3a2b0d1d83dff4ac4fe78d6d5673c27fc29b7f21a41d75f83a36be09f82a61c367b56aa73c1ff9 + version: 3.2.2 + resolution: "istanbul-lib-coverage@npm:3.2.2" + checksum: 2367407a8d13982d8f7a859a35e7f8dd5d8f75aae4bb5484ede3a9ea1b426dc245aff28b976a2af48ee759fdd9be374ce2bd2669b644f31e76c5f46a2e29a831 languageName: node linkType: hard @@ -11278,19 +12435,6 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.0.3": - version: 2.3.3 - resolution: "jackspeak@npm:2.3.3" - dependencies: - "@isaacs/cliui": ^8.0.2 - "@pkgjs/parseargs": ^0.11.0 - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 4313a7c0cc44c7753c4cb9869935f0b06f4cf96827515f63f58ff46b3d2f6e29aba6b3b5151778397c3f5ae67ef8bfc48871967bd10343c27e90cff198ec7808 - languageName: node - linkType: hard - "jackspeak@npm:^2.3.5": version: 2.3.6 resolution: "jackspeak@npm:2.3.6" @@ -11341,16 +12485,16 @@ __metadata: languageName: node linkType: hard -"jiti@npm:^1.18.2": - version: 1.20.0 - resolution: "jiti@npm:1.20.0" +"jiti@npm:^1.18.2, jiti@npm:^1.20.0": + version: 1.21.0 + resolution: "jiti@npm:1.21.0" bin: jiti: bin/jiti.js - checksum: 7924062b5675142e3e272a27735be84b7bfc0a0eb73217fc2dcafa034f37c4f7b4b9ffc07dd98bcff0f739a8811ce1544db205ae7e97b1c86f0df92c65ce3c72 + checksum: a7bd5d63921c170eaec91eecd686388181c7828e1fa0657ab374b9372bfc1f383cf4b039e6b272383d5cb25607509880af814a39abdff967322459cca41f2961 languageName: node linkType: hard -"joi@npm:^17.6.0": +"joi@npm:^17.6.0, joi@npm:^17.9.2": version: 17.11.0 resolution: "joi@npm:17.11.0" dependencies: @@ -11363,6 +12507,13 @@ __metadata: languageName: node linkType: hard +"js-base64@npm:^3.7.5": + version: 3.7.5 + resolution: "js-base64@npm:3.7.5" + checksum: 67a78c8b1c47b73f1c6fba1957e9fe6fd9dc78ac93ac46cc2e43472dcb9cf150d126fb0e593192e88e0497354fa634d17d255add7cc6ee3c7b4d29870faa8e18 + languageName: node + linkType: hard + "js-sdsl@npm:^4.1.4": version: 4.4.2 resolution: "js-sdsl@npm:4.4.2" @@ -11377,13 +12528,6 @@ __metadata: languageName: node linkType: hard -"js-string-escape@npm:^1.0.1": - version: 1.0.1 - resolution: "js-string-escape@npm:1.0.1" - checksum: f11e0991bf57e0c183b55c547acec85bd2445f043efc9ea5aa68b41bd2a3e7d3ce94636cb233ae0d84064ba4c1a505d32e969813c5b13f81e7d4be12c59256fe - languageName: node - linkType: hard - "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -11402,7 +12546,7 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^3.13.1, js-yaml@npm:^3.14.1": +"js-yaml@npm:^3.13.1": version: 3.14.1 resolution: "js-yaml@npm:3.14.1" dependencies: @@ -11527,14 +12671,14 @@ __metadata: languageName: node linkType: hard -"katex@npm:^0.13.0": - version: 0.13.24 - resolution: "katex@npm:0.13.24" +"katex@npm:^0.16.0": + version: 0.16.9 + resolution: "katex@npm:0.16.9" dependencies: - commander: ^8.0.0 + commander: ^8.3.0 bin: katex: cli.js - checksum: 1b7c8295867073d0db4f6fb41ef1c0e3418b8e23924ff61b446b36134cb74cdadc7242dfbfb922d9c32f0b15eda6160a08cd30948c4e78141966ca2991a1726b + checksum: 861194dfd4d86505e657f688fb73048d46ac498edafce71199502a35b03c0ecc35ba930c631be79c4a09d90a0d23476673cd52f6bc367c7a161854d64005fa95 languageName: node linkType: hard @@ -11569,11 +12713,11 @@ __metadata: linkType: hard "keyv@npm:^4.5.3": - version: 4.5.3 - resolution: "keyv@npm:4.5.3" + version: 4.5.4 + resolution: "keyv@npm:4.5.4" dependencies: json-buffer: 3.0.1 - checksum: 3ffb4d5b72b6b4b4af443bbb75ca2526b23c750fccb5ac4c267c6116888b4b65681015c2833cb20d26cf3e6e32dac6b988c77f7f022e1a571b7d90f1442257da + checksum: 74a24395b1c34bd44ad5cb2b49140d087553e170625240b86755a6604cd65aa16efdbdeae5cdb17ba1284a0fbb25ad06263755dbc71b8d8b06f74232ce3cdd72 languageName: node linkType: hard @@ -11706,6 +12850,15 @@ __metadata: languageName: node linkType: hard +"latest-version@npm:^7.0.0": + version: 7.0.0 + resolution: "latest-version@npm:7.0.0" + dependencies: + package-json: ^8.1.0 + checksum: 1f0deba00d5a34394cce4463c938811f51bbb539b131674f4bb2062c63f2cc3b80bccd56ecade3bd5932d04a34cf0a5a8a2ccc4ec9e5e6b285a9a7b3e27d0d66 + languageName: node + linkType: hard + "launch-editor@npm:^2.6.0": version: 2.6.1 resolution: "launch-editor@npm:2.6.1" @@ -11784,13 +12937,6 @@ __metadata: languageName: node linkType: hard -"load-json-file@npm:^7.0.0": - version: 7.0.1 - resolution: "load-json-file@npm:7.0.1" - checksum: a560288da6891778321ef993e4bdbdf05374a4f3a3aeedd5ba6b64672798c830d748cfc59a2ec9891a3db30e78b3d04172e0dcb0d4828168289a393147ca0e74 - languageName: node - linkType: hard - "loader-runner@npm:^4.2.0": version: 4.3.0 resolution: "loader-runner@npm:4.3.0" @@ -11877,13 +13023,6 @@ __metadata: languageName: node linkType: hard -"lodash.curry@npm:^4.0.1": - version: 4.1.1 - resolution: "lodash.curry@npm:4.1.1" - checksum: 9192b70fe7df4d1ff780c0260bee271afa9168c93fe4fa24bc861900240531b59781b5fdaadf4644fea8f4fbcd96f0700539ab294b579ffc1022c6c15dcc462a - languageName: node - linkType: hard - "lodash.debounce@npm:^4.0.8": version: 4.0.8 resolution: "lodash.debounce@npm:4.0.8" @@ -11891,34 +13030,6 @@ __metadata: languageName: node linkType: hard -"lodash.escape@npm:^4.0.1": - version: 4.0.1 - resolution: "lodash.escape@npm:4.0.1" - checksum: fcb54f457497256964d619d5cccbd80a961916fca60df3fe0fa3e7f052715c2944c0ed5aefb4f9e047d127d44aa2d55555f3350cb42c6549e9e293fb30b41e7f - languageName: node - linkType: hard - -"lodash.flatten@npm:^4.4.0": - version: 4.4.0 - resolution: "lodash.flatten@npm:4.4.0" - checksum: 0ac34a393d4b795d4b7421153d27c13ae67e08786c9cbb60ff5b732210d46f833598eee3fb3844bb10070e8488efe390ea53bb567377e0cb47e9e630bf0811cb - languageName: node - linkType: hard - -"lodash.flow@npm:^3.3.0": - version: 3.5.0 - resolution: "lodash.flow@npm:3.5.0" - checksum: a9a62ad344e3c5a1f42bc121da20f64dd855aaafecee24b1db640f29b88bd165d81c37ff7e380a7191de6f70b26f5918abcebbee8396624f78f3618a0b18634c - languageName: node - linkType: hard - -"lodash.invokemap@npm:^4.6.0": - version: 4.6.0 - resolution: "lodash.invokemap@npm:4.6.0" - checksum: 646ceebbefbcb6da301f8c2868254680fd0bcdc6ada470495d9ae49c9c32938829c1b38a38c95d0258409a9655f85db404b16e648381c7450b7ed3d9c52d8808 - languageName: node - linkType: hard - "lodash.isequal@npm:^4.5.0": version: 4.5.0 resolution: "lodash.isequal@npm:4.5.0" @@ -11940,13 +13051,6 @@ __metadata: languageName: node linkType: hard -"lodash.pullall@npm:^4.2.0": - version: 4.2.0 - resolution: "lodash.pullall@npm:4.2.0" - checksum: 7a5fbaedf186ec197ce1e0b9ba1d88a89773ebaf6a8291c7d273838cac59cb3b339cf36ef00e94172862ee84d2304c38face161846f08f5581d0553dcbdcd090 - languageName: node - linkType: hard - "lodash.uniq@npm:4.5.0, lodash.uniq@npm:^4.5.0": version: 4.5.0 resolution: "lodash.uniq@npm:4.5.0" @@ -11954,14 +13058,7 @@ __metadata: languageName: node linkType: hard -"lodash.uniqby@npm:^4.7.0": - version: 4.7.0 - resolution: "lodash.uniqby@npm:4.7.0" - checksum: 659264545a95726d1493123345aad8cbf56e17810fa9a0b029852c6d42bc80517696af09d99b23bef1845d10d95e01b8b4a1da578f22aeba7a30d3e0022a4938 - languageName: node - linkType: hard - -"lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21": +"lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -11990,6 +13087,13 @@ __metadata: languageName: node linkType: hard +"longest-streak@npm:^3.0.0": + version: 3.1.0 + resolution: "longest-streak@npm:3.1.0" + checksum: d7f952ed004cbdb5c8bcfc4f7f5c3d65449e6c5a9e9be4505a656e3df5a57ee125f284286b4bf8ecea0c21a7b3bf2b8f9001ad506c319b9815ad6a63a47d0fd0 + languageName: node + linkType: hard + "loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0, loose-envify@npm:^1.2.0, loose-envify@npm:^1.3.1, loose-envify@npm:^1.4.0": version: 1.4.0 resolution: "loose-envify@npm:1.4.0" @@ -12001,12 +13105,12 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^2.3.1": - version: 2.3.6 - resolution: "loupe@npm:2.3.6" +"loupe@npm:^2.3.6": + version: 2.3.7 + resolution: "loupe@npm:2.3.7" dependencies: - get-func-name: ^2.0.0 - checksum: cc83f1b124a1df7384601d72d8d1f5fe95fd7a8185469fec48bb2e4027e45243949e7a013e8d91051a138451ff0552310c32aa9786e60b6a30d1e801bdc2163f + get-func-name: ^2.0.1 + checksum: 96c058ec7167598e238bb7fb9def2f9339215e97d6685d9c1e3e4bdb33d14600e11fe7a812cf0c003dfb73ca2df374f146280b2287cae9e8d989e9d7a69a203b languageName: node linkType: hard @@ -12033,6 +13137,20 @@ __metadata: languageName: node linkType: hard +"lowercase-keys@npm:^3.0.0": + version: 3.0.0 + resolution: "lowercase-keys@npm:3.0.0" + checksum: 67a3f81409af969bc0c4ca0e76cd7d16adb1e25aa1c197229587eaf8671275c8c067cd421795dbca4c81be0098e4c426a086a05e30de8a9c587b7a13c0c7ccc5 + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.1.0 + resolution: "lru-cache@npm:10.1.0" + checksum: 58056d33e2500fbedce92f8c542e7c11b50d7d086578f14b7074d8c241422004af0718e08a6eaae8705cee09c77e39a61c1c79e9370ba689b7010c152e6a76ab + languageName: node + linkType: hard + "lru-cache@npm:^5.1.1": version: 5.1.1 resolution: "lru-cache@npm:5.1.1" @@ -12051,13 +13169,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^7.7.1": - version: 7.18.3 - resolution: "lru-cache@npm:7.18.3" - checksum: e550d772384709deea3f141af34b6d4fa392e2e418c1498c078de0ee63670f1f46f5eee746e8ef7e69e1c895af0d4224e62ee33e66a543a14763b0f2e74c1356 - languageName: node - linkType: hard - "lru-cache@npm:^8.0.4": version: 8.0.5 resolution: "lru-cache@npm:8.0.5" @@ -12065,13 +13176,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.0.1 - resolution: "lru-cache@npm:10.0.1" - checksum: 06f8d0e1ceabd76bb6f644a26dbb0b4c471b79c7b514c13c6856113879b3bf369eb7b497dad4ff2b7e2636db202412394865b33c332100876d838ad1372f0181 - languageName: node - linkType: hard - "lru_map@npm:^0.3.3": version: 0.3.3 resolution: "lru_map@npm:0.3.3" @@ -12118,35 +13222,22 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^11.0.3": - version: 11.1.1 - resolution: "make-fetch-happen@npm:11.1.1" +"make-fetch-happen@npm:^13.0.0": + version: 13.0.0 + resolution: "make-fetch-happen@npm:13.0.0" dependencies: - agentkeepalive: ^4.2.1 - cacache: ^17.0.0 + "@npmcli/agent": ^2.0.0 + cacache: ^18.0.0 http-cache-semantics: ^4.1.1 - http-proxy-agent: ^5.0.0 - https-proxy-agent: ^5.0.0 is-lambda: ^1.0.1 - lru-cache: ^7.7.1 - minipass: ^5.0.0 + minipass: ^7.0.2 minipass-fetch: ^3.0.0 minipass-flush: ^1.0.5 minipass-pipeline: ^1.2.4 negotiator: ^0.6.3 promise-retry: ^2.0.1 - socks-proxy-agent: ^7.0.0 ssri: ^10.0.0 - checksum: 7268bf274a0f6dcf0343829489a4506603ff34bd0649c12058753900b0eb29191dce5dba12680719a5d0a983d3e57810f594a12f3c18494e93a1fbc6348a4540 - languageName: node - linkType: hard - -"map-age-cleaner@npm:^0.1.3": - version: 0.1.3 - resolution: "map-age-cleaner@npm:0.1.3" - dependencies: - p-defer: ^1.0.0 - checksum: cb2804a5bcb3cbdfe4b59066ea6d19f5e7c8c196cd55795ea4c28f792b192e4c442426ae52524e5e1acbccf393d3bddacefc3d41f803e66453f6c4eda3650bc1 + checksum: 7c7a6d381ce919dd83af398b66459a10e2fe8f4504f340d1d090d3fa3d1b0c93750220e1d898114c64467223504bd258612ba83efbc16f31b075cd56de24b4af languageName: node linkType: hard @@ -12171,6 +13262,20 @@ __metadata: languageName: node linkType: hard +"markdown-extensions@npm:^2.0.0": + version: 2.0.0 + resolution: "markdown-extensions@npm:2.0.0" + checksum: ec4ffcb0768f112e778e7ac74cb8ef22a966c168c3e6c29829f007f015b0a0b5c79c73ee8599a0c72e440e7f5cfdbf19e80e2d77b9a313b8f66e180a330cf1b2 + languageName: node + linkType: hard + +"markdown-table@npm:^3.0.0": + version: 3.0.3 + resolution: "markdown-table@npm:3.0.3" + checksum: 8fcd3d9018311120fbb97115987f8b1665a603f3134c93fbecc5d1463380c8036f789e2a62c19432058829e594fff8db9ff81c88f83690b2f8ed6c074f8d9e10 + languageName: node + linkType: hard + "marked@npm:^4.3.0": version: 4.3.0 resolution: "marked@npm:4.3.0" @@ -12187,15 +13292,6 @@ __metadata: languageName: node linkType: hard -"matcher@npm:^5.0.0": - version: 5.0.0 - resolution: "matcher@npm:5.0.0" - dependencies: - escape-string-regexp: ^5.0.0 - checksum: 28f191c2d23fee0f6f32fd0181d9fe173b0ab815a919edba55605438a2f9fa40372e002574a1b17add981b0a8669c75bc6194318d065ed2dceffd8b160c38118 - languageName: node - linkType: hard - "mcl-wasm@npm:^0.7.1": version: 0.7.9 resolution: "mcl-wasm@npm:0.7.9" @@ -12203,15 +13299,6 @@ __metadata: languageName: node linkType: hard -"md5-hex@npm:^3.0.1": - version: 3.0.1 - resolution: "md5-hex@npm:3.0.1" - dependencies: - blueimp-md5: ^2.10.0 - checksum: 6799a19e8bdd3e0c2861b94c1d4d858a89220488d7885c1fa236797e367d0c2e5f2b789e05309307083503f85be3603a9686a5915568a473137d6b4117419cc2 - languageName: node - linkType: hard - "md5.js@npm:^1.3.4": version: 1.3.5 resolution: "md5.js@npm:1.3.5" @@ -12241,6 +13328,232 @@ __metadata: languageName: node linkType: hard +"mdast-util-directive@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-directive@npm:3.0.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + devlop: ^1.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + parse-entities: ^4.0.0 + stringify-entities: ^4.0.0 + unist-util-visit-parents: ^6.0.0 + checksum: 593afdc4f39f99bb198f3774bf4648cb546cb99a055e40c82262a7faab10926d2529a725d0d3945300ed0a1f07c6c84215a3f76b899a89b3f410ec7375bbab17 + languageName: node + linkType: hard + +"mdast-util-find-and-replace@npm:^3.0.0, mdast-util-find-and-replace@npm:^3.0.1": + version: 3.0.1 + resolution: "mdast-util-find-and-replace@npm:3.0.1" + dependencies: + "@types/mdast": ^4.0.0 + escape-string-regexp: ^5.0.0 + unist-util-is: ^6.0.0 + unist-util-visit-parents: ^6.0.0 + checksum: 05d5c4ff02e31db2f8a685a13bcb6c3f44e040bd9dfa54c19a232af8de5268334c8755d79cb456ed4cced1300c4fb83e88444c7ae8ee9ff16869a580f29d08cd + languageName: node + linkType: hard + +"mdast-util-from-markdown@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-from-markdown@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + mdast-util-to-string: ^4.0.0 + micromark: ^4.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-decode-string: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + unist-util-stringify-position: ^4.0.0 + checksum: 4e8d8a46b4b588486c41b80c39da333a91593bc8d60cd7421c6cd3c22003b8e5a62478292fb7bc97b9255b6301a2250cca32340ef43c309156e215453c5b92be + languageName: node + linkType: hard + +"mdast-util-frontmatter@npm:^2.0.0": + version: 2.0.1 + resolution: "mdast-util-frontmatter@npm:2.0.1" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + escape-string-regexp: ^5.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + micromark-extension-frontmatter: ^2.0.0 + checksum: 86a7c8d9eb183be2621d6d9134b9d33df2a3647e3255f68a9796e2425e25643ffae00a501e36c57d9c10973087b94aa5a2ffd865d33cdd274cc9b88cd2d90a2e + languageName: node + linkType: hard + +"mdast-util-gfm-autolink-literal@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-autolink-literal@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + ccount: ^2.0.0 + devlop: ^1.0.0 + mdast-util-find-and-replace: ^3.0.0 + micromark-util-character: ^2.0.0 + checksum: 10322662e5302964bed7c9829c5fd3b0c9899d4f03e63fb8620ab141cf4f3de9e61fcb4b44d46aacc8a23f82bcd5d900980a211825dfe026b1dab5fdbc3e8742 + languageName: node + linkType: hard + +"mdast-util-gfm-footnote@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-footnote@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.1.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + checksum: 45d26b40e7a093712e023105791129d76e164e2168d5268e113298a22de30c018162683fb7893cdc04ab246dac0087eed708b2a136d1d18ed2b32b3e0cae4a79 + languageName: node + linkType: hard + +"mdast-util-gfm-strikethrough@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-strikethrough@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: fe9b1d0eba9b791ff9001c008744eafe3dd7a81b085f2bf521595ce4a8e8b1b44764ad9361761ad4533af3e5d913d8ad053abec38172031d9ee32a8ebd1c7dbd + languageName: node + linkType: hard + +"mdast-util-gfm-table@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-table@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + markdown-table: ^3.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 063a627fd0993548fd63ca0c24c437baf91ba7d51d0a38820bd459bc20bf3d13d7365ef8d28dca99176dd5eb26058f7dde51190479c186dfe6af2e11202957c9 + languageName: node + linkType: hard + +"mdast-util-gfm-task-list-item@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-gfm-task-list-item@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 37db90c59b15330fc54d790404abf5ef9f2f83e8961c53666fe7de4aab8dd5e6b3c296b6be19797456711a89a27840291d8871ff0438e9b4e15c89d170efe072 + languageName: node + linkType: hard + +"mdast-util-gfm@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-gfm@npm:3.0.0" + dependencies: + mdast-util-from-markdown: ^2.0.0 + mdast-util-gfm-autolink-literal: ^2.0.0 + mdast-util-gfm-footnote: ^2.0.0 + mdast-util-gfm-strikethrough: ^2.0.0 + mdast-util-gfm-table: ^2.0.0 + mdast-util-gfm-task-list-item: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 62039d2f682ae3821ea1c999454863d31faf94d67eb9b746589c7e136076d7fb35fabc67e02f025c7c26fd7919331a0ee1aabfae24f565d9a6a9ebab3371c626 + languageName: node + linkType: hard + +"mdast-util-math@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-math@npm:3.0.0" + dependencies: + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + longest-streak: ^3.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.1.0 + unist-util-remove-position: ^5.0.0 + checksum: dc7dfb14aec2ec143420f2d92f80c5e6d69293d7cfb6b8180e7f411ce4e1314b5cf4a8d3345eefe06ab0ddd95e3c7801c4174b343fd2c26741180ca4dbad5371 + languageName: node + linkType: hard + +"mdast-util-mdx-expression@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-mdx-expression@npm:2.0.0" + dependencies: + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 4e1183000e183e07a7264e192889b4fd57372806103031c71b9318967f85fd50a5dd0f92ef14f42c331e77410808f5de3341d7bc8ad4ee91b7fa8f0a30043a8a + languageName: node + linkType: hard + +"mdast-util-mdx-jsx@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-mdx-jsx@npm:3.0.0" + dependencies: + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + ccount: ^2.0.0 + devlop: ^1.1.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + parse-entities: ^4.0.0 + stringify-entities: ^4.0.0 + unist-util-remove-position: ^5.0.0 + unist-util-stringify-position: ^4.0.0 + vfile-message: ^4.0.0 + checksum: 48fe1ba617205f3776ca2030d195adbdb42bb6c53326534db3f5bdd28abe7895103af8c4dfda7cbe2911e8cd71921bc8a82fe40856565e57af8b4f8a79c8c126 + languageName: node + linkType: hard + +"mdast-util-mdx@npm:^3.0.0": + version: 3.0.0 + resolution: "mdast-util-mdx@npm:3.0.0" + dependencies: + mdast-util-from-markdown: ^2.0.0 + mdast-util-mdx-expression: ^2.0.0 + mdast-util-mdx-jsx: ^3.0.0 + mdast-util-mdxjs-esm: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: e2b007d826fcd49fd57ed03e190753c8b0f7d9eff6c7cb26ba609cde15cd3a472c0cd5e4a1ee3e39a40f14be22fdb57de243e093cea0c064d6f3366cff3e3af2 + languageName: node + linkType: hard + +"mdast-util-mdxjs-esm@npm:^2.0.0": + version: 2.0.1 + resolution: "mdast-util-mdxjs-esm@npm:2.0.1" + dependencies: + "@types/estree-jsx": ^1.0.0 + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + checksum: 1f9dad04d31d59005332e9157ea9510dc1d03092aadbc607a10475c7eec1c158b475aa0601a3a4f74e13097ca735deb8c2d9d37928ddef25d3029fd7c9e14dc3 + languageName: node + linkType: hard + +"mdast-util-phrasing@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-util-phrasing@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + unist-util-is: ^6.0.0 + checksum: 95d5d8e18d5ea6dbfe2ee4ed1045961372efae9077e5c98e10bfef7025ee3fd9449f9a82840068ff50aa98fa43af0a0a14898ae10b5e46e96edde01e2797df34 + languageName: node + linkType: hard + "mdast-util-to-hast@npm:10.0.1": version: 10.0.1 resolution: "mdast-util-to-hast@npm:10.0.1" @@ -12257,6 +13570,38 @@ __metadata: languageName: node linkType: hard +"mdast-util-to-hast@npm:^13.0.0": + version: 13.0.2 + resolution: "mdast-util-to-hast@npm:13.0.2" + dependencies: + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + "@ungap/structured-clone": ^1.0.0 + devlop: ^1.0.0 + micromark-util-sanitize-uri: ^2.0.0 + trim-lines: ^3.0.0 + unist-util-position: ^5.0.0 + unist-util-visit: ^5.0.0 + checksum: 8fef6c3752476461d9c00b1dea4f141bc7d980e1b3bac7bd965bc68f532b6d30fb1c9e810433327c167176e68e071b8f4ab5a45355954857dc095c878421f35e + languageName: node + linkType: hard + +"mdast-util-to-markdown@npm:^2.0.0, mdast-util-to-markdown@npm:^2.1.0": + version: 2.1.0 + resolution: "mdast-util-to-markdown@npm:2.1.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + longest-streak: ^3.0.0 + mdast-util-phrasing: ^4.0.0 + mdast-util-to-string: ^4.0.0 + micromark-util-decode-string: ^2.0.0 + unist-util-visit: ^5.0.0 + zwitch: ^2.0.0 + checksum: 3a2cf3957e23b34e2e092e6e76ae72ee0b8745955bd811baba6814cf3a3d916c3fd52264b4b58f3bb3d512a428f84a1e998b6fc7e28434e388a9ae8fb6a9c173 + languageName: node + linkType: hard + "mdast-util-to-string@npm:^2.0.0": version: 2.0.0 resolution: "mdast-util-to-string@npm:2.0.0" @@ -12264,6 +13609,15 @@ __metadata: languageName: node linkType: hard +"mdast-util-to-string@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-util-to-string@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + checksum: 35489fb5710d58cbc2d6c8b6547df161a3f81e0f28f320dfb3548a9393555daf07c310c0c497708e67ed4dfea4a06e5655799e7d631ca91420c288b4525d6c29 + languageName: node + linkType: hard + "mdn-data@npm:2.0.14": version: 2.0.14 resolution: "mdn-data@npm:2.0.14" @@ -12285,16 +13639,6 @@ __metadata: languageName: node linkType: hard -"mem@npm:^9.0.2": - version: 9.0.2 - resolution: "mem@npm:9.0.2" - dependencies: - map-age-cleaner: ^0.1.3 - mimic-fn: ^4.0.0 - checksum: 07829bb182af0e3ecf748dc2edb1c3b10a256ef10458f7e24d06561a2adc2b3ef34d14abe81678bbcedb46faa477e7370223f118b1a5e1252da5fe43496f3967 - languageName: node - linkType: hard - "memfs@npm:^3.1.2, memfs@npm:^3.4.3": version: 3.5.3 resolution: "memfs@npm:3.5.3" @@ -12350,6 +13694,519 @@ __metadata: languageName: node linkType: hard +"micromark-core-commonmark@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-core-commonmark@npm:2.0.0" + dependencies: + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + micromark-factory-destination: ^2.0.0 + micromark-factory-label: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-factory-title: ^2.0.0 + micromark-factory-whitespace: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-classify-character: ^2.0.0 + micromark-util-html-tag-name: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-subtokenize: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 9c12fb580cf4ce71f60872043bd2794efe129f44d7b2b73afa155bbc0a66b7bc35655ba8cef438a6bd068441837ed3b6dc6ad7e5a18f815462c1750793e03a42 + languageName: node + linkType: hard + +"micromark-extension-directive@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-directive@npm:3.0.0" + dependencies: + devlop: ^1.0.0 + micromark-factory-space: ^2.0.0 + micromark-factory-whitespace: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + parse-entities: ^4.0.0 + checksum: 8350106bdf039a544cba64cf7932261a710e07d73d43d6c645dd2b16577f30ebd04abf762e8ca74266f5de19938e1eeff6c237d79f8244dea23aef7f90df2c31 + languageName: node + linkType: hard + +"micromark-extension-frontmatter@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-frontmatter@npm:2.0.0" + dependencies: + fault: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: f68032df38c00ae47de15b63bcd72515bfcce39de4a9262a3a1ac9c5990f253f8e41bdc65fd17ec4bb3d144c32529ce0829571331e4901a9a413f1a53785d1e8 + languageName: node + linkType: hard + +"micromark-extension-gfm-autolink-literal@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-autolink-literal@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-sanitize-uri: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: fa16d59528239262d6d04d539a052baf1f81275954ec8bfadea40d81bfc25667d5c8e68b225a5358626df5e30a3933173a67fdad2fed011d37810a10b770b0b2 + languageName: node + linkType: hard + +"micromark-extension-gfm-footnote@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-footnote@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-core-commonmark: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-sanitize-uri: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: a426fddecfac6144fc622b845cd2dc09d46faa75be5b76ff022cb76a03301b1d4929a5e5e41e071491787936be65e03d0b03c7aebc0e0136b3cdbfadadd6632c + languageName: node + linkType: hard + +"micromark-extension-gfm-strikethrough@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-strikethrough@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-classify-character: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 4e35fbbf364bfce08066b70acd94b9d393a8fd09a5afbe0bae70d0c8a174640b1ba86ab6b78ee38f411a813e2a718b07959216cf0063d823ba1c569a7694e5ad + languageName: node + linkType: hard + +"micromark-extension-gfm-table@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-table@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 71484dcf8db7b189da0528f472cc81e4d6d1a64ae43bbe7fcb7e2e1dba758a0a4f785f9f1afb9459fe5b4a02bbe023d78c95c05204414a14083052eb8219e5eb + languageName: node + linkType: hard + +"micromark-extension-gfm-tagfilter@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-gfm-tagfilter@npm:2.0.0" + dependencies: + micromark-util-types: ^2.0.0 + checksum: cf21552f4a63592bfd6c96ae5d64a5f22bda4e77814e3f0501bfe80e7a49378ad140f827007f36044666f176b3a0d5fea7c2e8e7973ce4b4579b77789f01ae95 + languageName: node + linkType: hard + +"micromark-extension-gfm-task-list-item@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-extension-gfm-task-list-item@npm:2.0.1" + dependencies: + devlop: ^1.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 80e569ab1a1d1f89d86af91482e9629e24b7e3f019c9d7989190f36a9367c6de723b2af48e908c1b73479f35b2215d3d38c1fdbf02ab01eb2fc90a59d1cf4465 + languageName: node + linkType: hard + +"micromark-extension-gfm@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-gfm@npm:3.0.0" + dependencies: + micromark-extension-gfm-autolink-literal: ^2.0.0 + micromark-extension-gfm-footnote: ^2.0.0 + micromark-extension-gfm-strikethrough: ^2.0.0 + micromark-extension-gfm-table: ^2.0.0 + micromark-extension-gfm-tagfilter: ^2.0.0 + micromark-extension-gfm-task-list-item: ^2.0.0 + micromark-util-combine-extensions: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 2060fa62666a09532d6b3a272d413bc1b25bbb262f921d7402795ac021e1362c8913727e33d7528d5b4ccaf26922ec51208c43f795a702964817bc986de886c9 + languageName: node + linkType: hard + +"micromark-extension-math@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-math@npm:3.0.0" + dependencies: + "@types/katex": ^0.16.0 + devlop: ^1.0.0 + katex: ^0.16.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 14d313ea58f711d69c567951870f8d8517384cd90318d8b608b4eabb2fea2278c7de1ca38fa86067704cba679b5a82be243680436c1bc26c4c4978b28fdf647c + languageName: node + linkType: hard + +"micromark-extension-mdx-expression@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-mdx-expression@npm:3.0.0" + dependencies: + "@types/estree": ^1.0.0 + devlop: ^1.0.0 + micromark-factory-mdx-expression: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-events-to-acorn: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: abd6ba0acdebc03bc0836c51a1ec4ca28e0be86f10420dd8cfbcd6c10dd37cd3f31e7c8b9792e9276e7526748883f4a30d0803d72b6285dae47d4e5348c23a10 + languageName: node + linkType: hard + +"micromark-extension-mdx-jsx@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-mdx-jsx@npm:3.0.0" + dependencies: + "@types/acorn": ^4.0.0 + "@types/estree": ^1.0.0 + devlop: ^1.0.0 + estree-util-is-identifier-name: ^3.0.0 + micromark-factory-mdx-expression: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + vfile-message: ^4.0.0 + checksum: 5e2f45d381d1ce43afadc5376427b42ef8cd2a574ca3658473254eabe84db99ef1abc03055b3d86728fac7f1edfb1076e6f2f322ed8bfb1f2f14cafc2c8f0d0e + languageName: node + linkType: hard + +"micromark-extension-mdx-md@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-mdx-md@npm:2.0.0" + dependencies: + micromark-util-types: ^2.0.0 + checksum: 7daf03372fd7faddf3f0ac87bdb0debb0bb770f33b586f72251e1072b222ceee75400ab6194c0e130dbf1e077369a5b627be6e9130d7a2e9e6b849f0d18ff246 + languageName: node + linkType: hard + +"micromark-extension-mdxjs-esm@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-mdxjs-esm@npm:3.0.0" + dependencies: + "@types/estree": ^1.0.0 + devlop: ^1.0.0 + micromark-core-commonmark: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-events-to-acorn: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + unist-util-position-from-estree: ^2.0.0 + vfile-message: ^4.0.0 + checksum: fb33d850200afce567b95c90f2f7d42259bd33eea16154349e4fa77c3ec934f46c8e5c111acea16321dce3d9f85aaa4c49afe8b810e31b34effc11617aeee8f6 + languageName: node + linkType: hard + +"micromark-extension-mdxjs@npm:^3.0.0": + version: 3.0.0 + resolution: "micromark-extension-mdxjs@npm:3.0.0" + dependencies: + acorn: ^8.0.0 + acorn-jsx: ^5.0.0 + micromark-extension-mdx-expression: ^3.0.0 + micromark-extension-mdx-jsx: ^3.0.0 + micromark-extension-mdx-md: ^2.0.0 + micromark-extension-mdxjs-esm: ^3.0.0 + micromark-util-combine-extensions: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 7da6f0fb0e1e0270a2f5ad257e7422cc16e68efa7b8214c63c9d55bc264cb872e9ca4ac9a71b9dfd13daf52e010f730bac316086f4340e4fcc6569ec699915bf + languageName: node + linkType: hard + +"micromark-factory-destination@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-destination@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: d36e65ed1c072ff4148b016783148ba7c68a078991154625723e24bda3945160268fb91079fb28618e1613c2b6e70390a8ddc544c45410288aa27b413593071a + languageName: node + linkType: hard + +"micromark-factory-label@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-label@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: c021dbd0ed367610d35f2bae21209bc804d1a6d1286ffce458fd6a717f4d7fe581a7cba7d5c2d7a63757c44eb927c80d6a571d6ea7969fae1b48ab6461d109c4 + languageName: node + linkType: hard + +"micromark-factory-mdx-expression@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-factory-mdx-expression@npm:2.0.1" + dependencies: + "@types/estree": ^1.0.0 + devlop: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-events-to-acorn: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + unist-util-position-from-estree: ^2.0.0 + vfile-message: ^4.0.0 + checksum: 2ba0ae939d0174a5e5331b1a4c203b96862ccf06e8903d6bdcc2d51f75515e52d407cd394afcd182f9ff0e877dc2a14e3fa430ced0131e156650d45104de8311 + languageName: node + linkType: hard + +"micromark-factory-space@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-factory-space@npm:1.1.0" + dependencies: + micromark-util-character: ^1.0.0 + micromark-util-types: ^1.0.0 + checksum: b58435076b998a7e244259a4694eb83c78915581206b6e7fc07b34c6abd36a1726ade63df8972fbf6c8fa38eecb9074f4e17be8d53f942e3b3d23d1a0ecaa941 + languageName: node + linkType: hard + +"micromark-factory-space@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-space@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 4ffdcdc2f759887bbb356500cb460b3915ecddcb5d85c3618d7df68ad05d13ed02b1153ee1845677b7d8126df8f388288b84fcf0d943bd9c92bcc71cd7222e37 + languageName: node + linkType: hard + +"micromark-factory-title@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-title@npm:2.0.0" + dependencies: + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 39e1ac23af3554e6e652e56065579bc7faf21ade7b8704b29c175871b4152b7109b790bb3cae0f7e088381139c6bac9553b8400772c3d322e4fa635f813a3578 + languageName: node + linkType: hard + +"micromark-factory-whitespace@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-whitespace@npm:2.0.0" + dependencies: + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 9587c2546d1a58b4d5472b42adf05463f6212d0449455285662d63cd8eaed89c6b159ac82713fcee5f9dd88628c24307d9533cccd8971a2f3f4d48702f8f850a + languageName: node + linkType: hard + +"micromark-util-character@npm:^1.0.0, micromark-util-character@npm:^1.1.0": + version: 1.2.0 + resolution: "micromark-util-character@npm:1.2.0" + dependencies: + micromark-util-symbol: ^1.0.0 + micromark-util-types: ^1.0.0 + checksum: 089e79162a19b4a28731736246579ab7e9482ac93cd681c2bfca9983dcff659212ef158a66a5957e9d4b1dba957d1b87b565d85418a5b009f0294f1f07f2aaac + languageName: node + linkType: hard + +"micromark-util-character@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-util-character@npm:2.0.1" + dependencies: + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 318d6e16fdcbe9d89e18b8e7796568d986abbb10a9f3037b7ac9b92a236bcc962f3cd380e26a7c49df40fd1d9ca33eb546268956345b662f4c4ca4962c7695f2 + languageName: node + linkType: hard + +"micromark-util-chunked@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-chunked@npm:2.0.0" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: 324f95cccdae061332a8241936eaba6ef0782a1e355bac5c607ad2564fd3744929be7dc81651315a2921535747a33243e6a5606bcb64b7a56d49b6d74ea1a3d4 + languageName: node + linkType: hard + +"micromark-util-classify-character@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-classify-character@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 086e52904deffebb793fb1c08c94aabb8901f76958142dfc3a6282890ebaa983b285e69bd602b9d507f1b758ed38e75a994d2ad9fbbefa7de2584f67a16af405 + languageName: node + linkType: hard + +"micromark-util-combine-extensions@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-combine-extensions@npm:2.0.0" + dependencies: + micromark-util-chunked: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 107c47700343f365b4ed81551e18bc3458b573c500e56ac052b2490bd548adc475216e41d2271633a8867fac66fc22ba3e0a2d74a31ed79b9870ca947eb4e3ba + languageName: node + linkType: hard + +"micromark-util-decode-numeric-character-reference@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-util-decode-numeric-character-reference@npm:2.0.1" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: 9512507722efd2033a9f08715eeef787fbfe27e23edf55db21423d46d82ab46f76c89b4f960be3f5e50a2d388d89658afc0647989cf256d051e9ea01277a1adb + languageName: node + linkType: hard + +"micromark-util-decode-string@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-decode-string@npm:2.0.0" + dependencies: + decode-named-character-reference: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-symbol: ^2.0.0 + checksum: a75daf32a4a6b549e9f19b4d833ebfeb09a32a9a1f9ce50f35dec6b6a3e4f9f121f49024ba7f9c91c55ebe792f7c7a332fc9604795181b6a612637df0df5b959 + languageName: node + linkType: hard + +"micromark-util-encode@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-encode@npm:2.0.0" + checksum: 853a3f33fce72aaf4ffa60b7f2b6fcfca40b270b3466e1b96561b02185d2bd8c01dd7948bc31a24ac014f4cc854e545ca9a8e9cf7ea46262f9d24c9e88551c66 + languageName: node + linkType: hard + +"micromark-util-events-to-acorn@npm:^2.0.0": + version: 2.0.2 + resolution: "micromark-util-events-to-acorn@npm:2.0.2" + dependencies: + "@types/acorn": ^4.0.0 + "@types/estree": ^1.0.0 + "@types/unist": ^3.0.0 + devlop: ^1.0.0 + estree-util-visit: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + vfile-message: ^4.0.0 + checksum: bcb3eeac52a4ae5c3ca3d8cff514de3a7d1f272d9a94cce26a08c578bef64df4d61820874c01207e92fcace9eae5c9a7ecdddef0c6e10014b255a07b7880bf94 + languageName: node + linkType: hard + +"micromark-util-html-tag-name@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-html-tag-name@npm:2.0.0" + checksum: d786d4486f93eb0ac5b628779809ca97c5dc60f3c9fc03eb565809831db181cf8cb7f05f9ac76852f3eb35461af0f89fa407b46f3a03f4f97a96754d8dc540d8 + languageName: node + linkType: hard + +"micromark-util-normalize-identifier@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-normalize-identifier@npm:2.0.0" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: b36da2d3fd102053dadd953ce5c558328df12a63a8ac0e5aad13d4dda8e43b6a5d4a661baafe0a1cd8a260bead4b4a8e6e0e74193dd651e8484225bd4f4e68aa + languageName: node + linkType: hard + +"micromark-util-resolve-all@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-resolve-all@npm:2.0.0" + dependencies: + micromark-util-types: ^2.0.0 + checksum: 31fe703b85572cb3f598ebe32750e59516925c7ff1f66cfe6afaebe0771a395a9eaa770787f2523d3c46082ea80e6c14f83643303740b3d650af7c96ebd30ccc + languageName: node + linkType: hard + +"micromark-util-sanitize-uri@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-sanitize-uri@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-encode: ^2.0.0 + micromark-util-symbol: ^2.0.0 + checksum: ea4c28bbffcf2430e9aff2d18554296789a8b0a1f54ac24020d1dde76624a7f93e8f2a83e88cd5a846b6d2c4287b71b1142d1b89fa7f1b0363a9b33711a141fe + languageName: node + linkType: hard + +"micromark-util-subtokenize@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-subtokenize@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 77d9c7d59c05a20468d49ce2a3640e9cb268c083ccad02322f26c84e1094c25b44f4b8139ef0a247ca11a4fef7620c5bf82fbffd98acdb2989e79cbe7bd8f1db + languageName: node + linkType: hard + +"micromark-util-symbol@npm:^1.0.0, micromark-util-symbol@npm:^1.0.1": + version: 1.1.0 + resolution: "micromark-util-symbol@npm:1.1.0" + checksum: 02414a753b79f67ff3276b517eeac87913aea6c028f3e668a19ea0fc09d98aea9f93d6222a76ca783d20299af9e4b8e7c797fe516b766185dcc6e93290f11f88 + languageName: node + linkType: hard + +"micromark-util-symbol@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-symbol@npm:2.0.0" + checksum: fa4a05bff575d9fbf0ad96a1013003e3bb6087ed6b34b609a141b6c0d2137b57df594aca409a95f4c5fda199f227b56a7d8b1f82cea0768df161d8a3a3660764 + languageName: node + linkType: hard + +"micromark-util-types@npm:^1.0.0": + version: 1.1.0 + resolution: "micromark-util-types@npm:1.1.0" + checksum: b0ef2b4b9589f15aec2666690477a6a185536927ceb7aa55a0f46475852e012d75a1ab945187e5c7841969a842892164b15d58ff8316b8e0d6cc920cabd5ede7 + languageName: node + linkType: hard + +"micromark-util-types@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-types@npm:2.0.0" + checksum: 819fef3ab5770c37893d2a60381fb2694396c8d22803b6e103c830c3a1bc1490363c2b0470bb2acaaddad776dfbc2fc1fcfde39cb63c4f54d95121611672e3d0 + languageName: node + linkType: hard + +"micromark@npm:^4.0.0": + version: 4.0.0 + resolution: "micromark@npm:4.0.0" + dependencies: + "@types/debug": ^4.0.0 + debug: ^4.0.0 + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + micromark-core-commonmark: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-combine-extensions: ^2.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-encode: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-sanitize-uri: ^2.0.0 + micromark-util-subtokenize: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: b84ab5ab1a0b28c063c52e9c2c9d7d44b954507235c10c9492d66e0b38f7de24bf298f914a1fbdf109f2a57a88cf0412de217c84cfac5fd60e3e42a74dbac085 + languageName: node + linkType: hard + "micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": version: 4.0.5 resolution: "micromatch@npm:4.0.5" @@ -12422,7 +14279,21 @@ __metadata: languageName: node linkType: hard -"mini-css-extract-plugin@npm:^2.6.1": +"mimic-response@npm:^3.1.0": + version: 3.1.0 + resolution: "mimic-response@npm:3.1.0" + checksum: 25739fee32c17f433626bf19f016df9036b75b3d84a3046c7d156e72ec963dd29d7fc8a302f55a3d6c5a4ff24259676b15d915aad6480815a969ff2ec0836867 + languageName: node + linkType: hard + +"mimic-response@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-response@npm:4.0.0" + checksum: 33b804cc961efe206efdb1fca6a22540decdcfce6c14eb5c0c50e5ae9022267ab22ce8f5568b1f7247ba67500fe20d523d81e0e9f009b321ccd9d472e78d1850 + languageName: node + linkType: hard + +"mini-css-extract-plugin@npm:^2.6.1, mini-css-extract-plugin@npm:^2.7.6": version: 2.7.6 resolution: "mini-css-extract-plugin@npm:2.7.6" dependencies: @@ -12481,12 +14352,12 @@ __metadata: languageName: node linkType: hard -"minipass-collect@npm:^1.0.2": - version: 1.0.2 - resolution: "minipass-collect@npm:1.0.2" +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" dependencies: - minipass: ^3.0.0 - checksum: 14df761028f3e47293aee72888f2657695ec66bd7d09cae7ad558da30415fdc4752bbfee66287dcc6fd5e6a2fa3466d6c484dc1cbd986525d9393b9523d97f10 + minipass: ^7.0.3 + checksum: b251bceea62090f67a6cced7a446a36f4cd61ee2d5cea9aee7fff79ba8030e416327a1c5aa2908dc22629d06214b46d88fdab8c51ac76bacbf5703851b5ad342 languageName: node linkType: hard @@ -12548,10 +14419,10 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.3": - version: 7.0.3 - resolution: "minipass@npm:7.0.3" - checksum: 6f1614f5b5b55568a46bca5fec0e7c46dac027691db27d0e1923a8192866903144cd962ac772c0e9f89b608ea818b702709c042bce98e190d258847d85461531 +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": + version: 7.0.4 + resolution: "minipass@npm:7.0.4" + checksum: 87585e258b9488caf2e7acea242fd7856bbe9a2c84a7807643513a338d66f368c7d518200ad7b70a508664d408aa000517647b2930c259a8b1f9f0984f344a21 languageName: node linkType: hard @@ -12647,6 +14518,34 @@ __metadata: languageName: node linkType: hard +"monaco-editor-textmate@npm:^4.0.0": + version: 4.0.0 + resolution: "monaco-editor-textmate@npm:4.0.0" + peerDependencies: + monaco-editor: 0.x.x + monaco-textmate: ^3.0.0 + checksum: 9d3f5f24982f928c5f4b7c5c5170a549cb19eb1471eb157aa07bd97cf15cd75dd941585eeb6924b05c54109a55d48adc45191eda9db5d2793b1d8c462181c100 + languageName: node + linkType: hard + +"monaco-editor@npm:^0.44.0": + version: 0.44.0 + resolution: "monaco-editor@npm:0.44.0" + checksum: 6e561b23e5e9090cbdbb820dae5895a8bf9d537acc09281756a8c428960da0481461c72f387cc9a2e14bff69ab4359186c98df2dd29d6d109f1ab7189b573a35 + languageName: node + linkType: hard + +"monaco-textmate@npm:^3.0.1": + version: 3.0.1 + resolution: "monaco-textmate@npm:3.0.1" + dependencies: + fast-plist: ^0.1.2 + peerDependencies: + onigasm: ^2.0.0 + checksum: 0f2ec07ee3e9a37bb880e2aaef802f82cb666660b40fc3c7c3e35553d740aed34ae94399b06296fddf1f96efdaf27eaf347b39cb14bc08ccfb65162c52771d56 + languageName: node + linkType: hard + "mri@npm:^1.1.0": version: 1.2.0 resolution: "mri@npm:1.2.0" @@ -12675,7 +14574,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3": +"ms@npm:2.1.3, ms@npm:^2.1.1": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -12710,12 +14609,12 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.1.25, nanoid@npm:^3.3.6": - version: 3.3.6 - resolution: "nanoid@npm:3.3.6" +"nanoid@npm:^3.1.25, nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" bin: nanoid: bin/nanoid.cjs - checksum: 7d0eda657002738aa5206107bd0580aead6c95c460ef1bdd0b1a87a9c7ae6277ac2e9b945306aaa5b32c6dcb7feaf462d0f552e7f8b5718abfc6ead5c94a71b3 + checksum: d36c427e530713e4ac6567d488b489a36582ef89da1d6d4e3b87eded11eb10d7042a877958c6f104929809b2ab0bafa17652b076cdf84324aa75b30b722204f2 languageName: node linkType: hard @@ -12782,6 +14681,18 @@ __metadata: languageName: node linkType: hard +"node-emoji@npm:^2.1.0": + version: 2.1.3 + resolution: "node-emoji@npm:2.1.3" + dependencies: + "@sindresorhus/is": ^4.6.0 + char-regex: ^1.0.2 + emojilib: ^2.4.0 + skin-tone: ^2.0.0 + checksum: 9ae5a1fb12fd5ce6885f251f345986115de4bb82e7d06fdc943845fb19260d89d0aaaccbaf85cae39fe7aaa1fc391640558865ba690c9bb8a7236c3ac10bbab0 + languageName: node + linkType: hard + "node-fetch@npm:2.6.7": version: 2.6.7 resolution: "node-fetch@npm:2.6.7" @@ -12807,20 +14718,6 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.12": - version: 2.7.0 - resolution: "node-fetch@npm:2.7.0" - dependencies: - whatwg-url: ^5.0.0 - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: d76d2f5edb451a3f05b15115ec89fc6be39de37c6089f1b6368df03b91e1633fd379a7e01b7ab05089a25034b2023d959b47e59759cb38d88341b2459e89d6e5 - languageName: node - linkType: hard - "node-forge@npm:^1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -12829,59 +14726,51 @@ __metadata: linkType: hard "node-gyp-build@npm:^4.2.0, node-gyp-build@npm:^4.3.0": - version: 4.6.1 - resolution: "node-gyp-build@npm:4.6.1" + version: 4.7.1 + resolution: "node-gyp-build@npm:4.7.1" bin: node-gyp-build: bin.js node-gyp-build-optional: optional.js node-gyp-build-test: build-test.js - checksum: c3676d337b36803bc7792e35bf7fdcda7cdcb7e289b8f9855a5535702a82498eb976842fefcf487258c58005ca32ce3d537fbed91280b04409161dcd7232a882 + checksum: 2ef8248021489db03be3e8098977cdc797b80a9b12b77c6dcb89b0dc89b8c62e6a482672ee298f61021740ae7f080fb33154cfec8fb158cec620f57b0fae87c0 languageName: node linkType: hard "node-gyp@npm:latest": - version: 9.4.0 - resolution: "node-gyp@npm:9.4.0" + version: 10.0.1 + resolution: "node-gyp@npm:10.0.1" dependencies: env-paths: ^2.2.0 exponential-backoff: ^3.1.1 - glob: ^7.1.4 + glob: ^10.3.10 graceful-fs: ^4.2.6 - make-fetch-happen: ^11.0.3 - nopt: ^6.0.0 - npmlog: ^6.0.0 - rimraf: ^3.0.2 + make-fetch-happen: ^13.0.0 + nopt: ^7.0.0 + proc-log: ^3.0.0 semver: ^7.3.5 tar: ^6.1.2 - which: ^2.0.2 + which: ^4.0.0 bin: node-gyp: bin/node-gyp.js - checksum: 78b404e2e0639d64e145845f7f5a3cb20c0520cdaf6dda2f6e025e9b644077202ea7de1232396ba5bde3fee84cdc79604feebe6ba3ec84d464c85d407bb5da99 - languageName: node - linkType: hard - -"node-releases@npm:^2.0.13": - version: 2.0.13 - resolution: "node-releases@npm:2.0.13" - checksum: 17ec8f315dba62710cae71a8dad3cd0288ba943d2ece43504b3b1aa8625bf138637798ab470b1d9035b0545996f63000a8a926e0f6d35d0996424f8b6d36dda3 + checksum: 60a74e66d364903ce02049966303a57f898521d139860ac82744a5fdd9f7b7b3b61f75f284f3bfe6e6add3b8f1871ce305a1d41f775c7482de837b50c792223f languageName: node linkType: hard -"nofilter@npm:^3.1.0": - version: 3.1.0 - resolution: "nofilter@npm:3.1.0" - checksum: 58aa85a5b4b35cbb6e42de8a8591c5e338061edc9f3e7286f2c335e9e9b9b8fa7c335ae45daa8a1f3433164dc0b9a3d187fa96f9516e04a17a1f9ce722becc4f +"node-releases@npm:^2.0.14": + version: 2.0.14 + resolution: "node-releases@npm:2.0.14" + checksum: 59443a2f77acac854c42d321bf1b43dea0aef55cd544c6a686e9816a697300458d4e82239e2d794ea05f7bbbc8a94500332e2d3ac3f11f52e4b16cbe638b3c41 languageName: node linkType: hard -"nopt@npm:^6.0.0": - version: 6.0.0 - resolution: "nopt@npm:6.0.0" +"nopt@npm:^7.0.0": + version: 7.2.0 + resolution: "nopt@npm:7.2.0" dependencies: - abbrev: ^1.0.0 + abbrev: ^2.0.0 bin: nopt: bin/nopt.js - checksum: 82149371f8be0c4b9ec2f863cc6509a7fd0fa729929c009f3a58e4eb0c9e4cae9920e8f1f8eb46e7d032fec8fb01bede7f0f41a67eb3553b7b8e14fa53de1dac + checksum: a9c0f57fb8cb9cc82ae47192ca2b7ef00e199b9480eed202482c962d61b59a7fbe7541920b2a5839a97b42ee39e288c0aed770e38057a608d7f579389dfde410 languageName: node linkType: hard @@ -12913,6 +14802,13 @@ __metadata: languageName: node linkType: hard +"normalize-url@npm:^8.0.0": + version: 8.0.0 + resolution: "normalize-url@npm:8.0.0" + checksum: 24c20b75ebfd526d8453084692720b49d111c63c0911f1b7447427829597841eef5a8ba3f6bb93d6654007b991c1f5cd85da2c907800e439e2e2ec6c2abd0fc0 + languageName: node + linkType: hard + "npm-run-path@npm:^4.0.1": version: 4.0.1 resolution: "npm-run-path@npm:4.0.1" @@ -12931,18 +14827,6 @@ __metadata: languageName: node linkType: hard -"npmlog@npm:^6.0.0": - version: 6.0.2 - resolution: "npmlog@npm:6.0.2" - dependencies: - are-we-there-yet: ^3.0.0 - console-control-strings: ^1.1.0 - gauge: ^4.0.3 - set-blocking: ^2.0.0 - checksum: ae238cd264a1c3f22091cdd9e2b106f684297d3c184f1146984ecbe18aaa86343953f26b9520dedd1b1372bc0316905b736c1932d778dbeb1fcf5a1001390e2a - languageName: node - linkType: hard - "nprogress@npm:^0.2.0": version: 0.2.0 resolution: "nprogress@npm:0.2.0" @@ -12959,7 +14843,7 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4.1.0, object-assign@npm:^4.1.1": +"object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f @@ -12967,9 +14851,9 @@ __metadata: linkType: hard "object-inspect@npm:^1.9.0": - version: 1.12.3 - resolution: "object-inspect@npm:1.12.3" - checksum: dabfd824d97a5f407e6d5d24810d888859f6be394d8b733a77442b277e0808860555176719c5905e765e3743a7cada6b8b0a3b85e5331c530fd418cc8ae991db + version: 1.13.1 + resolution: "object-inspect@npm:1.13.1" + checksum: 7d9fa9221de3311dcb5c7c307ee5dc011cdd31dc43624b7c184b3840514e118e05ef0002be5388304c416c0eb592feb46e983db12577fc47e47d5752fbbfb61f languageName: node linkType: hard @@ -12981,14 +14865,14 @@ __metadata: linkType: hard "object.assign@npm:^4.1.0": - version: 4.1.4 - resolution: "object.assign@npm:4.1.4" + version: 4.1.5 + resolution: "object.assign@npm:4.1.5" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.1.4 + call-bind: ^1.0.5 + define-properties: ^1.2.1 has-symbols: ^1.0.3 object-keys: ^1.1.1 - checksum: 76cab513a5999acbfe0ff355f15a6a125e71805fcf53de4e9d4e082e1989bdb81d1e329291e1e4e0ae7719f0e4ef80e88fb2d367ae60500d79d25a6224ac8864 + checksum: f9aeac0541661370a1fc86e6a8065eb1668d3e771f7dbb33ee54578201336c057b21ee61207a186dd42db0c62201d91aac703d20d12a79fc79c353eed44d4e25 languageName: node linkType: hard @@ -13049,6 +14933,15 @@ __metadata: languageName: node linkType: hard +"onigasm@npm:^2.2.5": + version: 2.2.5 + resolution: "onigasm@npm:2.2.5" + dependencies: + lru-cache: ^5.1.1 + checksum: 97aedde610ef561f05853609d6a5b720ec1e123f867bdac1b38b5aeb3bc90ed60209678c75a5f0f9821aa793c720b6d17aabfb956e26ab115ee9b81d6e56bdf7 + languageName: node + linkType: hard + "only@npm:~0.0.2": version: 0.0.2 resolution: "only@npm:0.0.2" @@ -13132,19 +15025,10 @@ __metadata: languageName: node linkType: hard -"p-defer@npm:^1.0.0": - version: 1.0.0 - resolution: "p-defer@npm:1.0.0" - checksum: 4271b935c27987e7b6f229e5de4cdd335d808465604644cb7b4c4c95bef266735859a93b16415af8a41fd663ee9e3b97a1a2023ca9def613dba1bad2a0da0c7b - languageName: node - linkType: hard - -"p-event@npm:^5.0.1": - version: 5.0.1 - resolution: "p-event@npm:5.0.1" - dependencies: - p-timeout: ^5.0.2 - checksum: 3bdd8df6092e6b149f25e9c2eb1c0843b3b4279b07be2a2c72c02b65b267a8908c2040fefd606f2497b0f2bcefcd214f8ca5a74f0c883515d400ccf1d88d5683 +"p-cancelable@npm:^3.0.0": + version: 3.0.0 + resolution: "p-cancelable@npm:3.0.0" + checksum: 2b5ae34218f9c2cf7a7c18e5d9a726ef9b165ef07e6c959f6738371509e747334b5f78f3bcdeb03d8a12dcb978faf641fd87eb21486ed7d36fb823b8ddef3219 languageName: node linkType: hard @@ -13238,15 +15122,6 @@ __metadata: languageName: node linkType: hard -"p-map@npm:^5.5.0": - version: 5.5.0 - resolution: "p-map@npm:5.5.0" - dependencies: - aggregate-error: ^4.0.0 - checksum: 065cb6fca6b78afbd070dd9224ff160dc23eea96e57863c09a0c8ea7ce921043f76854be7ee0abc295cff1ac9adcf700e79a1fbe3b80b625081087be58e7effb - languageName: node - linkType: hard - "p-retry@npm:^4.5.0": version: 4.6.2 resolution: "p-retry@npm:4.6.2" @@ -13257,13 +15132,6 @@ __metadata: languageName: node linkType: hard -"p-timeout@npm:^5.0.2": - version: 5.1.0 - resolution: "p-timeout@npm:5.1.0" - checksum: f5cd4e17301ff1ff1d8dbf2817df0ad88c6bba99349fc24d8d181827176ad4f8aca649190b8a5b1a428dfd6ddc091af4606835d3e0cb0656e04045da5c9e270c - languageName: node - linkType: hard - "p-try@npm:^1.0.0": version: 1.0.0 resolution: "p-try@npm:1.0.0" @@ -13290,6 +15158,18 @@ __metadata: languageName: node linkType: hard +"package-json@npm:^8.1.0": + version: 8.1.1 + resolution: "package-json@npm:8.1.1" + dependencies: + got: ^12.1.0 + registry-auth-token: ^5.0.1 + registry-url: ^6.0.0 + semver: ^7.3.7 + checksum: 28bec6f42bf9fba66b7c8fea07576fc23d08ec7923433f7835d6cd8654e72169d74f9738b3785107d18a476ae76712e0daeb1dddcd6930e69f9e4b47eba7c0ca + languageName: node + linkType: hard + "param-case@npm:^3.0.4": version: 3.0.4 resolution: "param-case@npm:3.0.4" @@ -13323,6 +15203,22 @@ __metadata: languageName: node linkType: hard +"parse-entities@npm:^4.0.0": + version: 4.0.1 + resolution: "parse-entities@npm:4.0.1" + dependencies: + "@types/unist": ^2.0.0 + character-entities: ^2.0.0 + character-entities-legacy: ^3.0.0 + character-reference-invalid: ^2.0.0 + decode-named-character-reference: ^1.0.0 + is-alphanumerical: ^2.0.0 + is-decimal: ^2.0.0 + is-hexadecimal: ^2.0.0 + checksum: 32a6ff5b9acb9d2c4d71537308521fd265e685b9215691df73feedd9edfe041bb6da9f89bd0c35c4a2bc7d58e3e76e399bb6078c2fd7d2a343ff1dd46edbf1bd + languageName: node + linkType: hard + "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -13335,13 +15231,6 @@ __metadata: languageName: node linkType: hard -"parse-ms@npm:^3.0.0": - version: 3.0.0 - resolution: "parse-ms@npm:3.0.0" - checksum: fc602bba093835562321a67a9d6c8c9687ca4f26a09459a77e07ebd7efddd1a5766725ec60eb0c83a2abe67f7a23808f7deb1c1226727776eaf7f9607ae09db2 - languageName: node - linkType: hard - "parse-numeric-range@npm:^1.3.0": version: 1.3.0 resolution: "parse-numeric-range@npm:1.3.0" @@ -13524,6 +15413,17 @@ __metadata: languageName: node linkType: hard +"periscopic@npm:^3.0.0": + version: 3.1.0 + resolution: "periscopic@npm:3.1.0" + dependencies: + "@types/estree": ^1.0.0 + estree-walker: ^3.0.0 + is-reference: ^3.0.0 + checksum: 2153244352e58a0d76e7e8d9263e66fe74509495f809af388da20045fb30aa3e93f2f94468dc0b9166ecf206fcfc0d73d2c7641c6fbedc07b1de858b710142cb + languageName: node + linkType: hard + "picocolors@npm:^1.0.0": version: 1.0.0 resolution: "picocolors@npm:1.0.0" @@ -13538,16 +15438,6 @@ __metadata: languageName: node linkType: hard -"pkg-conf@npm:^4.0.0": - version: 4.0.0 - resolution: "pkg-conf@npm:4.0.0" - dependencies: - find-up: ^6.0.0 - load-json-file: ^7.0.0 - checksum: 6da0c064a74f6c7ae80d7d68c5853e14f7e762a2a80c6ca9e0aa827002b90b69c86fefe3bac830b10a6f1739e7f96a1f728637f2a141e50b0fdafe92a2c3eab6 - languageName: node - linkType: hard - "pkg-dir@npm:^4.1.0": version: 4.2.0 resolution: "pkg-dir@npm:4.2.0" @@ -13557,6 +15447,15 @@ __metadata: languageName: node linkType: hard +"pkg-dir@npm:^7.0.0": + version: 7.0.0 + resolution: "pkg-dir@npm:7.0.0" + dependencies: + find-up: ^6.3.0 + checksum: 94298b20a446bfbbd66604474de8a0cdd3b8d251225170970f15d9646f633e056c80520dd5b4c1d1050c9fed8f6a9e5054b141c93806439452efe72e57562c03 + languageName: node + linkType: hard + "pkg-up@npm:^3.1.0": version: 3.1.0 resolution: "pkg-up@npm:3.1.0" @@ -13566,36 +15465,27 @@ __metadata: languageName: node linkType: hard -"playwright-core@npm:1.38.0": - version: 1.38.0 - resolution: "playwright-core@npm:1.38.0" +"playwright-core@npm:1.40.1": + version: 1.40.1 + resolution: "playwright-core@npm:1.40.1" bin: playwright-core: cli.js - checksum: 9eb43fc6c3cb392d5f35b0fd0b7291b38a8cbdc3cbb944a8261f744f30d09196dfa3b5d84aa02ffc09af87d08d31b385b007b6af20d0b6cd50a29344f3b0db8d + checksum: 84d92fb9b86e3c225b16b6886bf858eb5059b4e60fa1205ff23336e56a06dcb2eac62650992dede72f406c8e70a7b6a5303e511f9b4bc0b85022ede356a01ee0 languageName: node linkType: hard "playwright@npm:^1.22.2": - version: 1.38.0 - resolution: "playwright@npm:1.38.0" + version: 1.40.1 + resolution: "playwright@npm:1.40.1" dependencies: fsevents: 2.3.2 - playwright-core: 1.38.0 + playwright-core: 1.40.1 dependenciesMeta: fsevents: optional: true bin: playwright: cli.js - checksum: c5356690a391d5dd41f814d4e2694b93ba9e79381ce63de752da1c6c59b1f9c69bc6be853d973d0542d73a44a6b15f7c0081a164a64cd27b6b31207710c0ab34 - languageName: node - linkType: hard - -"plur@npm:^5.1.0": - version: 5.1.0 - resolution: "plur@npm:5.1.0" - dependencies: - irregular-plurals: ^3.3.0 - checksum: 57e400dc4b926768fb0abab7f8688fe17e85673712134546e7beaaee188bae7e0504976e847d7e41d0d6103ff2fd61204095f03c2a45de19a8bad15aecb45cc1 + checksum: 9e36791c1b4a649c104aa365fdd9d049924eeb518c5967c0e921aa38b9b00994aa6ee54784d6c2af194b3b494b6f69772673081ef53c6c4a4b2065af9955c4ba languageName: node linkType: hard @@ -13695,7 +15585,7 @@ __metadata: languageName: node linkType: hard -"postcss-loader@npm:^7.0.0": +"postcss-loader@npm:^7.0.0, postcss-loader@npm:^7.3.3": version: 7.3.3 resolution: "postcss-loader@npm:7.3.3" dependencies: @@ -13994,7 +15884,7 @@ __metadata: languageName: node linkType: hard -"postcss-sort-media-queries@npm:^4.2.1": +"postcss-sort-media-queries@npm:^4.2.1, postcss-sort-media-queries@npm:^4.4.1": version: 4.4.1 resolution: "postcss-sort-media-queries@npm:4.4.1" dependencies: @@ -14044,14 +15934,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.3.11, postcss@npm:^8.4.14, postcss@npm:^8.4.17, postcss@npm:^8.4.21": - version: 8.4.31 - resolution: "postcss@npm:8.4.31" +"postcss@npm:^8.4.14, postcss@npm:^8.4.17, postcss@npm:^8.4.21, postcss@npm:^8.4.26": + version: 8.4.32 + resolution: "postcss@npm:8.4.32" dependencies: - nanoid: ^3.3.6 + nanoid: ^3.3.7 picocolors: ^1.0.0 source-map-js: ^1.0.2 - checksum: 1d8611341b073143ad90486fcdfeab49edd243377b1f51834dc4f6d028e82ce5190e4f11bb2633276864503654fb7cab28e67abdc0fbf9d1f88cad4a0ff0beea + checksum: 220d9d0bf5d65be7ed31006c523bfb11619461d296245c1231831f90150aeb4a31eab9983ac9c5c89759a3ca8b60b3e0d098574964e1691673c3ce5c494305ae languageName: node linkType: hard @@ -14078,7 +15968,16 @@ __metadata: languageName: node linkType: hard -"prettier@npm:*, prettier@npm:3.0.3": +"prettier@npm:*": + version: 3.1.1 + resolution: "prettier@npm:3.1.1" + bin: + prettier: bin/prettier.cjs + checksum: e386855e3a1af86a748e16953f168be555ce66d6233f4ba54eb6449b88eb0c6b2ca79441b11eae6d28a7f9a5c96440ce50864b9d5f6356d331d39d6bb66c648e + languageName: node + linkType: hard + +"prettier@npm:3.0.3": version: 3.0.3 resolution: "prettier@npm:3.0.3" bin: @@ -14097,15 +15996,6 @@ __metadata: languageName: node linkType: hard -"pretty-ms@npm:^8.0.0": - version: 8.0.0 - resolution: "pretty-ms@npm:8.0.0" - dependencies: - parse-ms: ^3.0.0 - checksum: b7d2a8182887af0e5ab93f9df331f10db9b8eda86855e2de115eb01a6c501bde5631a8813b1b0abdd7d045e79b08ae875369a8fd279a3dacd6d9e572bdd3bfa6 - languageName: node - linkType: hard - "pretty-time@npm:^1.1.0": version: 1.1.0 resolution: "pretty-time@npm:1.1.0" @@ -14113,22 +16003,32 @@ __metadata: languageName: node linkType: hard -"prism-react-renderer@npm:^1.3.5": - version: 1.3.5 - resolution: "prism-react-renderer@npm:1.3.5" +"prism-react-renderer@npm:^2.1.0, prism-react-renderer@npm:^2.3.0": + version: 2.3.0 + resolution: "prism-react-renderer@npm:2.3.0" + dependencies: + "@types/prismjs": ^1.26.0 + clsx: ^2.0.0 peerDependencies: - react: ">=0.14.9" - checksum: c18806dcbc4c0b4fd6fd15bd06b4f7c0a6da98d93af235c3e970854994eb9b59e23315abb6cfc29e69da26d36709a47e25da85ab27fed81b6812f0a52caf6dfa + react: ">=16.0.0" + checksum: 29b24eb5015c09e1b7e3fa2941584ead6fceb5556fdfbe7c34548d96886e0b291290bda93a421aab8b26ce6aae677387aac294982d11349a050843f6dbbc7449 languageName: node linkType: hard -"prismjs@npm:^1.28.0": +"prismjs@npm:^1.29.0": version: 1.29.0 resolution: "prismjs@npm:1.29.0" checksum: 007a8869d4456ff8049dc59404e32d5666a07d99c3b0e30a18bd3b7676dfa07d1daae9d0f407f20983865fd8da56de91d09cb08e6aa61f5bc420a27c0beeaf93 languageName: node linkType: hard +"proc-log@npm:^3.0.0": + version: 3.0.0 + resolution: "proc-log@npm:3.0.0" + checksum: 02b64e1b3919e63df06f836b98d3af002b5cd92655cab18b5746e37374bfb73e03b84fe305454614b34c25b485cc687a9eebdccf0242cda8fda2475dd2c97e02 + languageName: node + linkType: hard + "process-nextick-args@npm:~2.0.0": version: 2.0.1 resolution: "process-nextick-args@npm:2.0.1" @@ -14153,15 +16053,6 @@ __metadata: languageName: node linkType: hard -"promise@npm:^7.1.1": - version: 7.3.1 - resolution: "promise@npm:7.3.1" - dependencies: - asap: ~2.0.3 - checksum: 475bb069130179fbd27ed2ab45f26d8862376a137a57314cf53310bdd85cc986a826fd585829be97ebc0aaf10e9d8e68be1bfe5a4a0364144b1f9eedfa940cf1 - languageName: node - linkType: hard - "prompts@npm:^2.4.2": version: 2.4.2 resolution: "prompts@npm:2.4.2" @@ -14192,6 +16083,20 @@ __metadata: languageName: node linkType: hard +"property-information@npm:^6.0.0": + version: 6.4.0 + resolution: "property-information@npm:6.4.0" + checksum: b5aed9a40e87730995f3ceed29839f137fa73b2a4cccfb8ed72ab8bddb8881cad05c3487c4aa168d7cb49a53db8089790c9f00f59d15b8380d2bb5383cdd1f24 + languageName: node + linkType: hard + +"proto-list@npm:~1.2.1": + version: 1.2.4 + resolution: "proto-list@npm:1.2.4" + checksum: 4d4826e1713cbfa0f15124ab0ae494c91b597a3c458670c9714c36e8baddf5a6aad22842776f2f5b137f259c8533e741771445eb8df82e861eea37a6eaba03f7 + languageName: node + linkType: hard + "proxy-addr@npm:~2.0.7": version: 2.0.7 resolution: "proxy-addr@npm:2.0.7" @@ -14238,9 +16143,9 @@ __metadata: linkType: hard "punycode@npm:^2.1.0, punycode@npm:^2.1.1": - version: 2.3.0 - resolution: "punycode@npm:2.3.0" - checksum: 39f760e09a2a3bbfe8f5287cf733ecdad69d6af2fe6f97ca95f24b8921858b91e9ea3c9eeec6e08cede96181b3bb33f95c6ffd8c77e63986508aa2e8159fa200 + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: bb0a0ceedca4c3c57a9b981b90601579058903c62be23c5e8e843d2c2d4148a3ecf029d5133486fb0e1822b098ba8bba09e89d6b21742d02fa26bda6441a6fb2 languageName: node linkType: hard @@ -14253,6 +16158,15 @@ __metadata: languageName: node linkType: hard +"pupa@npm:^3.1.0": + version: 3.1.0 + resolution: "pupa@npm:3.1.0" + dependencies: + escape-goat: ^4.0.0 + checksum: 0e4f4ab6bbdce600fa6d23b1833f1af57b2641246ff4cbe10f9d66e4e5479b0de2864a88d5bd629eef59524eda3c6680726acd7f3f873d9ed46b7f095d0bb5f6 + languageName: node + linkType: hard + "puppeteer-core@npm:^19.8.1": version: 19.11.1 resolution: "puppeteer-core@npm:19.11.1" @@ -14277,13 +16191,6 @@ __metadata: languageName: node linkType: hard -"pure-color@npm:^1.2.0": - version: 1.3.0 - resolution: "pure-color@npm:1.3.0" - checksum: 646d8bed6e6eab89affdd5e2c11f607a85b631a7fb03c061dfa658eb4dc4806881a15feed2ac5fd8c0bad8c00c632c640d5b1cb8b9a972e6e947393a1329371b - languageName: node - linkType: hard - "qs@npm:6.11.0": version: 6.11.0 resolution: "qs@npm:6.11.0" @@ -14318,6 +16225,13 @@ __metadata: languageName: node linkType: hard +"quick-lru@npm:^5.1.1": + version: 5.1.1 + resolution: "quick-lru@npm:5.1.1" + checksum: a516faa25574be7947969883e6068dbe4aa19e8ef8e8e0fd96cddd6d36485e9106d85c0041a27153286b0770b381328f4072aa40d3b18a19f5f7d2b78b94b5ed + languageName: node + linkType: hard + "randombytes@npm:^2.1.0": version: 2.1.0 resolution: "randombytes@npm:2.1.0" @@ -14365,7 +16279,7 @@ __metadata: languageName: node linkType: hard -"rc@npm:1.2.8, rc@npm:^1.2.8": +"rc@npm:1.2.8, rc@npm:^1.0.1, rc@npm:^1.1.6, rc@npm:^1.2.8": version: 1.2.8 resolution: "rc@npm:1.2.8" dependencies: @@ -14379,18 +16293,6 @@ __metadata: languageName: node linkType: hard -"react-base16-styling@npm:^0.6.0": - version: 0.6.0 - resolution: "react-base16-styling@npm:0.6.0" - dependencies: - base16: ^1.0.0 - lodash.curry: ^4.0.1 - lodash.flow: ^3.3.0 - pure-color: ^1.2.0 - checksum: 00a12dddafc8a9025cca933b0dcb65fca41c81fa176d1fc3a6a9d0242127042e2c0a604f4c724a3254dd2c6aeb5ef55095522ff22f5462e419641c1341a658e4 - languageName: node - linkType: hard - "react-dev-utils@npm:^12.0.1": version: 12.0.1 resolution: "react-dev-utils@npm:12.0.1" @@ -14423,16 +16325,15 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^17.0.2": - version: 17.0.2 - resolution: "react-dom@npm:17.0.2" +"react-dom@npm:^18.2.0": + version: 18.2.0 + resolution: "react-dom@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - scheduler: ^0.20.2 + scheduler: ^0.23.0 peerDependencies: - react: 17.0.2 - checksum: 1c1eaa3bca7c7228d24b70932e3d7c99e70d1d04e13bb0843bbf321582bc25d7961d6b8a6978a58a598af2af496d1cedcfb1bf65f6b0960a0a8161cb8dab743c + react: ^18.2.0 + checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc languageName: node linkType: hard @@ -14443,14 +16344,28 @@ __metadata: languageName: node linkType: hard -"react-fast-compare@npm:^3.2.0": +"react-fast-compare@npm:^3.2.0, react-fast-compare@npm:^3.2.2": version: 3.2.2 resolution: "react-fast-compare@npm:3.2.2" checksum: 2071415b4f76a3e6b55c84611c4d24dcb12ffc85811a2840b5a3f1ff2d1a99be1020d9437ee7c6e024c9f4cbb84ceb35e48cf84f28fcb00265ad2dfdd3947704 languageName: node linkType: hard -"react-helmet-async@npm:*, react-helmet-async@npm:^1.3.0": +"react-helmet-async@npm:*": + version: 2.0.3 + resolution: "react-helmet-async@npm:2.0.3" + dependencies: + invariant: ^2.2.4 + react-fast-compare: ^3.2.2 + shallowequal: ^1.1.0 + peerDependencies: + react: ^16.6.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0 + checksum: dfb951174c1812b1aaa8099181024ea8fbdc5cb65e5ab56e465753e2dc5a7c7756e9ab86ba382157ff27dc5b33353a2a000f7f088653815e4aa576daec01ec33 + languageName: node + linkType: hard + +"react-helmet-async@npm:^1.3.0": version: 1.3.0 resolution: "react-helmet-async@npm:1.3.0" dependencies: @@ -14473,25 +16388,12 @@ __metadata: languageName: node linkType: hard -"react-json-view@npm:^1.21.3": - version: 1.21.3 - resolution: "react-json-view@npm:1.21.3" - dependencies: - flux: ^4.0.1 - react-base16-styling: ^0.6.0 - react-lifecycles-compat: ^3.0.4 - react-textarea-autosize: ^8.3.2 +"react-json-view-lite@npm:^1.2.0": + version: 1.2.1 + resolution: "react-json-view-lite@npm:1.2.1" peerDependencies: - react: ^17.0.0 || ^16.3.0 || ^15.5.4 - react-dom: ^17.0.0 || ^16.3.0 || ^15.5.4 - checksum: 5718bcd9210ad5b06eb9469cf8b9b44be9498845a7702e621343618e8251f26357e6e1c865532cf170db6165df1cb30202787e057309d8848c220bc600ec0d1a - languageName: node - linkType: hard - -"react-lifecycles-compat@npm:^3.0.4": - version: 3.0.4 - resolution: "react-lifecycles-compat@npm:3.0.4" - checksum: a904b0fc0a8eeb15a148c9feb7bc17cec7ef96e71188280061fc340043fd6d8ee3ff233381f0e8f95c1cf926210b2c4a31f38182c8f35ac55057e453d6df204f + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + checksum: 9441260033ec07991b0121281d846f9d3e8db9061ea0dc3938f7003630f515d47870a465d90f1f9300ebe406679986657a4062c009c2a2084e2e145e6fa05a47 languageName: node linkType: hard @@ -14519,7 +16421,7 @@ __metadata: languageName: node linkType: hard -"react-router-dom@npm:^5.3.3": +"react-router-dom@npm:^5.3.3, react-router-dom@npm:^5.3.4": version: 5.3.4 resolution: "react-router-dom@npm:5.3.4" dependencies: @@ -14536,7 +16438,7 @@ __metadata: languageName: node linkType: hard -"react-router@npm:5.3.4, react-router@npm:^5.3.3": +"react-router@npm:5.3.4, react-router@npm:^5.3.3, react-router@npm:^5.3.4": version: 5.3.4 resolution: "react-router@npm:5.3.4" dependencies: @@ -14555,26 +16457,34 @@ __metadata: languageName: node linkType: hard -"react-textarea-autosize@npm:^8.3.2": - version: 8.5.3 - resolution: "react-textarea-autosize@npm:8.5.3" +"react-spinners@npm:^0.13.8": + version: 0.13.8 + resolution: "react-spinners@npm:0.13.8" + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 + checksum: cb58f916bbf00c4f7fc33c1a75a8c0f91a98a42af26944340a0e29e4b3a97937a03f0292bc444eb5f5f0bea099344b580f9c04a81524246dadbf0571bdb57e62 + languageName: node + linkType: hard + +"react-toastify@npm:^9.1.3": + version: 9.1.3 + resolution: "react-toastify@npm:9.1.3" dependencies: - "@babel/runtime": ^7.20.13 - use-composed-ref: ^1.3.0 - use-latest: ^1.2.1 + clsx: ^1.1.1 peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: b317c3763f37a89621bbafd0e6e2d068e7876790a5ae77f497adfd6ba9334ceea138c8a0b7d907bae0f79c765cb24e8b2ca2b8033b4144c0bce28571a3658921 + react: ">=16" + react-dom: ">=16" + checksum: e8bd92c5cbf831b43a042644ab9bc69abe6ceb3ce91ba71f5cd2d8b6a2c9885ca52770e1f1ba64c5632607f6df962db344a26c7fba57606faf5aa0e7bfc8535f languageName: node linkType: hard -"react@npm:^17.0.2": - version: 17.0.2 - resolution: "react@npm:17.0.2" +"react@npm:^18.2.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: b254cc17ce3011788330f7bbf383ab653c6848902d7936a87b09d835d091e3f295f7e9dd1597c6daac5dc80f90e778c8230218ba8ad599f74adcc11e33b9d61b + checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b languageName: node linkType: hard @@ -14691,6 +16601,16 @@ __metadata: languageName: node linkType: hard +"registry-auth-token@npm:3.3.2": + version: 3.3.2 + resolution: "registry-auth-token@npm:3.3.2" + dependencies: + rc: ^1.1.6 + safe-buffer: ^5.0.1 + checksum: c9d7ae160a738f1fa825556e3669e6c771d2c0239ce37679f7e8646157a97d0a76464738be075002a1f754ef9bfb913b689f4bbfd5296d28f136fbf98c8c2217 + languageName: node + linkType: hard + "registry-auth-token@npm:^4.0.0": version: 4.2.2 resolution: "registry-auth-token@npm:4.2.2" @@ -14700,6 +16620,24 @@ __metadata: languageName: node linkType: hard +"registry-auth-token@npm:^5.0.1": + version: 5.0.2 + resolution: "registry-auth-token@npm:5.0.2" + dependencies: + "@pnpm/npm-conf": ^2.1.0 + checksum: 0d7683b71ee418993e7872b389024b13645c4295eb7bb850d10728eaf46065db24ea4d47dc6cbb71a60d1aa4bef077b0d8b7363c9ac9d355fdba47bebdfb01dd + languageName: node + linkType: hard + +"registry-url@npm:3.1.0": + version: 3.1.0 + resolution: "registry-url@npm:3.1.0" + dependencies: + rc: ^1.0.1 + checksum: 6d223da41b04e1824f5faa63905c6f2e43b216589d72794111573f017352b790aef42cd1f826463062f89d804abb2027e3d9665d2a9a0426a11eedd04d470af3 + languageName: node + linkType: hard + "registry-url@npm:^5.0.0": version: 5.1.0 resolution: "registry-url@npm:5.1.0" @@ -14709,6 +16647,15 @@ __metadata: languageName: node linkType: hard +"registry-url@npm:^6.0.0": + version: 6.0.1 + resolution: "registry-url@npm:6.0.1" + dependencies: + rc: 1.2.8 + checksum: 33712aa1b489aab7aba2191c1cdadfdd71f5bf166d4792d81744a6be332c160bd7d9273af8269d8a01284b9562f14a5b31b7abcf7ad9306c44887ecff51c89ab + languageName: node + linkType: hard + "regjsparser@npm:^0.9.1": version: 0.9.1 resolution: "regjsparser@npm:0.9.1" @@ -14720,27 +16667,29 @@ __metadata: languageName: node linkType: hard -"rehype-katex@npm:^5.0.0": - version: 5.0.0 - resolution: "rehype-katex@npm:5.0.0" +"rehype-katex@npm:^7.0.0": + version: 7.0.0 + resolution: "rehype-katex@npm:7.0.0" dependencies: - "@types/katex": ^0.11.0 - hast-util-to-text: ^2.0.0 - katex: ^0.13.0 - rehype-parse: ^7.0.0 - unified: ^9.0.0 - unist-util-visit: ^2.0.0 - checksum: b20e24c5326a718581619761057a30d03615519eccd0693ada2c7c710064dceaf08f038ae3a1131550f1f7c47ca54a254ba8e45547da384867e956ceca73f6bf + "@types/hast": ^3.0.0 + "@types/katex": ^0.16.0 + hast-util-from-html-isomorphic: ^2.0.0 + hast-util-to-text: ^4.0.0 + katex: ^0.16.0 + unist-util-visit-parents: ^6.0.0 + vfile: ^6.0.0 + checksum: 3184cf7635e63039a5d455e27718cbc99998cc7bfcc15422badf5da892887f4200f3ee54a6617aa231aa15d46cb678716c112b6b7f9cef11a8653e5d518ad6f0 languageName: node linkType: hard -"rehype-parse@npm:^7.0.0": - version: 7.0.1 - resolution: "rehype-parse@npm:7.0.1" +"rehype-raw@npm:^7.0.0": + version: 7.0.0 + resolution: "rehype-raw@npm:7.0.0" dependencies: - hast-util-from-parse5: ^6.0.0 - parse5: ^6.0.0 - checksum: c3c914aa9281853290eff6b09e0bed6843934e788b957e25219e91f0bf244a183d2f5e042c7d21543276571f9b49a6bae90f4640b8f885f2773392ffa57baf4b + "@types/hast": ^3.0.0 + hast-util-raw: ^9.0.0 + vfile: ^6.0.0 + checksum: f9e28dcbf4c6c7d91a97c10a840310f18ef3268aa45abb3e0428b6b191ff3c4fa8f753b910d768588a2dac5c7da7e557b4ddc3f1b6cd252e8d20cb62d60c65ed languageName: node linkType: hard @@ -14760,6 +16709,18 @@ __metadata: languageName: unknown linkType: soft +"remark-directive@npm:^3.0.0": + version: 3.0.0 + resolution: "remark-directive@npm:3.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-directive: ^3.0.0 + micromark-extension-directive: ^3.0.0 + unified: ^11.0.0 + checksum: 744d12bbe924bd0492a2481cbaf9250aa6622c0d2cc090bb7bc39975e355c8a46ae13cc4793204ada39f0af64c953f6b730a55420a50375e0f74a5dd5d201089 + languageName: node + linkType: hard + "remark-emoji@npm:^2.2.0": version: 2.2.0 resolution: "remark-emoji@npm:2.2.0" @@ -14771,6 +16732,19 @@ __metadata: languageName: node linkType: hard +"remark-emoji@npm:^4.0.0": + version: 4.0.1 + resolution: "remark-emoji@npm:4.0.1" + dependencies: + "@types/mdast": ^4.0.2 + emoticon: ^4.0.1 + mdast-util-find-and-replace: ^3.0.1 + node-emoji: ^2.1.0 + unified: ^11.0.4 + checksum: 2c02d8c0b694535a9f0c4fe39180cb89a8fbd07eb873c94842c34dfde566b8a6703df9d28fe175a8c28584f96252121de722862baa756f2d875f2f1a4352c1f4 + languageName: node + linkType: hard + "remark-footnotes@npm:2.0.0": version: 2.0.0 resolution: "remark-footnotes@npm:2.0.0" @@ -14778,10 +16752,41 @@ __metadata: languageName: node linkType: hard -"remark-math@npm:^3.0.1": - version: 3.0.1 - resolution: "remark-math@npm:3.0.1" - checksum: 690256f27f2b42dadcf41806fec443056e09592454622ae77f03b1a8474e8c83cc7610e694be7e17de92c96cc272c61209e59a6e7a24e3af6ede47d48b185ccd +"remark-frontmatter@npm:^5.0.0": + version: 5.0.0 + resolution: "remark-frontmatter@npm:5.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-frontmatter: ^2.0.0 + micromark-extension-frontmatter: ^2.0.0 + unified: ^11.0.0 + checksum: b36e11d528d1d0172489c74ce7961bb6073f7272e71ea1349f765fc79c4246a758aef949174d371a088c48e458af776fcfbb3b043c49cd1120ca8239aeafe16a + languageName: node + linkType: hard + +"remark-gfm@npm:^4.0.0": + version: 4.0.0 + resolution: "remark-gfm@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-gfm: ^3.0.0 + micromark-extension-gfm: ^3.0.0 + remark-parse: ^11.0.0 + remark-stringify: ^11.0.0 + unified: ^11.0.0 + checksum: 84bea84e388061fbbb697b4b666089f5c328aa04d19dc544c229b607446bc10902e46b67b9594415a1017bbbd7c811c1f0c30d36682c6d1a6718b66a1558261b + languageName: node + linkType: hard + +"remark-math@npm:^6.0.0": + version: 6.0.0 + resolution: "remark-math@npm:6.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-math: ^3.0.0 + micromark-extension-math: ^3.0.0 + unified: ^11.0.0 + checksum: fef489acb6cae6e40af05012367dc22a846ce16301e8a96006c6d78935887bdb3e6c5018b6514884ecee57f9c7a51f97a10862526ab0a0f5f7b7d339fe0eb20f languageName: node linkType: hard @@ -14801,6 +16806,16 @@ __metadata: languageName: node linkType: hard +"remark-mdx@npm:^3.0.0": + version: 3.0.0 + resolution: "remark-mdx@npm:3.0.0" + dependencies: + mdast-util-mdx: ^3.0.0 + micromark-extension-mdxjs: ^3.0.0 + checksum: 8b9b3e5297e5cb4c312553f42c3720280ada96ae60ede880606924a0aad2e773106aba1ef45a0c179c218f8da6f58dac3c789a9c4f791649ca7a183706cde5b8 + languageName: node + linkType: hard + "remark-parse@npm:8.0.3": version: 8.0.3 resolution: "remark-parse@npm:8.0.3" @@ -14825,6 +16840,31 @@ __metadata: languageName: node linkType: hard +"remark-parse@npm:^11.0.0": + version: 11.0.0 + resolution: "remark-parse@npm:11.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-from-markdown: ^2.0.0 + micromark-util-types: ^2.0.0 + unified: ^11.0.0 + checksum: d83d245290fa84bb04fb3e78111f09c74f7417e7c012a64dd8dc04fccc3699036d828fbd8eeec8944f774b6c30cc1d925c98f8c46495ebcee7c595496342ab7f + languageName: node + linkType: hard + +"remark-rehype@npm:^11.0.0": + version: 11.0.0 + resolution: "remark-rehype@npm:11.0.0" + dependencies: + "@types/hast": ^3.0.0 + "@types/mdast": ^4.0.0 + mdast-util-to-hast: ^13.0.0 + unified: ^11.0.0 + vfile: ^6.0.0 + checksum: 0ff0fd948759cbde9d507ca1581028d0b89da0b5f610b35a6cb0a511f8d11621449b6eca573b11ddaea77afd37edd4755f3f1eb086ad49a6f7b970b4a4634e13 + languageName: node + linkType: hard + "remark-squeeze-paragraphs@npm:4.0.0": version: 4.0.0 resolution: "remark-squeeze-paragraphs@npm:4.0.0" @@ -14834,6 +16874,17 @@ __metadata: languageName: node linkType: hard +"remark-stringify@npm:^11.0.0": + version: 11.0.0 + resolution: "remark-stringify@npm:11.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-to-markdown: ^2.0.0 + unified: ^11.0.0 + checksum: 59e07460eb629d6c3b3c0f438b0b236e7e6858fd5ab770303078f5a556ec00354d9c7fb9ef6d5f745a4617ac7da1ab618b170fbb4dac120e183fecd9cc86bce6 + languageName: node + linkType: hard + "renderkid@npm:^3.0.0": version: 3.0.0 resolution: "renderkid@npm:3.0.0" @@ -14847,7 +16898,7 @@ __metadata: languageName: node linkType: hard -"repeat-string@npm:^1.0.0, repeat-string@npm:^1.5.4": +"repeat-string@npm:^1.5.4": version: 1.6.1 resolution: "repeat-string@npm:1.6.1" checksum: 1b809fc6db97decdc68f5b12c4d1a671c8e3f65ec4a40c238bc5200e44e85bcc52a54f78268ab9c29fcf5fe4f1343e805420056d1f30fa9a9ee4c2d93e3cc6c0 @@ -14882,12 +16933,10 @@ __metadata: languageName: node linkType: hard -"resolve-cwd@npm:^3.0.0": - version: 3.0.0 - resolution: "resolve-cwd@npm:3.0.0" - dependencies: - resolve-from: ^5.0.0 - checksum: 546e0816012d65778e580ad62b29e975a642989108d9a3c5beabfb2304192fa3c9f9146fbdfe213563c6ff51975ae41bac1d3c6e047dd9572c94863a057b4d81 +"resolve-alpn@npm:^1.2.0": + version: 1.2.1 + resolution: "resolve-alpn@npm:1.2.1" + checksum: f558071fcb2c60b04054c99aebd572a2af97ef64128d59bef7ab73bd50d896a222a056de40ffc545b633d99b304c259ea9d0c06830d5c867c34f0bfa60b8eae0 languageName: node linkType: hard @@ -14898,13 +16947,6 @@ __metadata: languageName: node linkType: hard -"resolve-from@npm:^5.0.0": - version: 5.0.0 - resolution: "resolve-from@npm:5.0.0" - checksum: 4ceeb9113e1b1372d0cd969f3468fa042daa1dd9527b1b6bb88acb6ab55d8b9cd65dbf18819f9f9ddf0db804990901dcdaade80a215e7b2c23daae38e64f5bdf - languageName: node - linkType: hard - "resolve-path@npm:^1.4.0": version: 1.4.0 resolution: "resolve-path@npm:1.4.0" @@ -14922,6 +16964,13 @@ __metadata: languageName: node linkType: hard +"resolve-pkg-maps@npm:^1.0.0": + version: 1.0.0 + resolution: "resolve-pkg-maps@npm:1.0.0" + checksum: 1012afc566b3fdb190a6309cc37ef3b2dcc35dff5fa6683a9d00cd25c3247edfbc4691b91078c97adc82a29b77a2660c30d791d65dab4fc78bfc473f60289977 + languageName: node + linkType: hard + "resolve@npm:1.17.0": version: 1.17.0 resolution: "resolve@npm:1.17.0" @@ -14931,7 +16980,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.14.2, resolve@npm:^1.3.2": +"resolve@npm:^1.1.6, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.3.2": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -14944,19 +16993,6 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.19.0": - version: 1.22.6 - resolution: "resolve@npm:1.22.6" - dependencies: - is-core-module: ^2.13.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: d13bf66d4e2ee30d291491f16f2fa44edd4e0cefb85d53249dd6f93e70b2b8c20ec62f01b18662e3cd40e50a7528f18c4087a99490048992a3bb954cf3201a5b - languageName: node - linkType: hard - "resolve@patch:resolve@1.17.0#~builtin": version: 1.17.0 resolution: "resolve@patch:resolve@npm%3A1.17.0#~builtin::version=1.17.0&hash=c3c19d" @@ -14966,7 +17002,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.3.2#~builtin": +"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.3.2#~builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin::version=1.22.8&hash=c3c19d" dependencies: @@ -14979,19 +17015,6 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.19.0#~builtin": - version: 1.22.6 - resolution: "resolve@patch:resolve@npm%3A1.22.6#~builtin::version=1.22.6&hash=c3c19d" - dependencies: - is-core-module: ^2.13.0 - path-parse: ^1.0.7 - supports-preserve-symlinks-flag: ^1.0.0 - bin: - resolve: bin/resolve - checksum: 9d3b3c67aefd12cecbe5f10ca4d1f51ea190891096497c43f301b086883b426466918c3a64f1bbf1788fabb52b579d58809614006c5d0b49186702b3b8fb746a - languageName: node - linkType: hard - "responselike@npm:^1.0.2": version: 1.0.2 resolution: "responselike@npm:1.0.2" @@ -15001,6 +17024,15 @@ __metadata: languageName: node linkType: hard +"responselike@npm:^3.0.0": + version: 3.0.0 + resolution: "responselike@npm:3.0.0" + dependencies: + lowercase-keys: ^3.0.0 + checksum: e0cc9be30df4f415d6d83cdede3c5c887cd4a73e7cc1708bcaab1d50a28d15acb68460ac5b02bcc55a42f3d493729c8856427dcf6e57e6e128ad05cba4cfb95e + languageName: node + linkType: hard + "restore-cursor@npm:^3.1.0": version: 3.1.0 resolution: "restore-cursor@npm:3.1.0" @@ -15090,23 +17122,23 @@ __metadata: linkType: hard "rtl-detect@npm:^1.0.4": - version: 1.0.4 - resolution: "rtl-detect@npm:1.0.4" - checksum: d562535baa0db62f57f0a1d4676297bff72fd6b94e88f0f0900d5c3e810ab512c5c4cadffd3e05fbe8d9c74310c919afa3ea8c1001c244e5555e8eef12d02d6f + version: 1.1.2 + resolution: "rtl-detect@npm:1.1.2" + checksum: 4a43a1e5df0617eb86d5485640b318787d12b86acf53d840a3b2ff701ee941e95479d4e9ae97e907569ec763d1c47218cb87639bc87bcdad60a85747e5270cf0 languageName: node linkType: hard -"rtlcss@npm:^3.5.0": - version: 3.5.0 - resolution: "rtlcss@npm:3.5.0" +"rtlcss@npm:^4.1.0": + version: 4.1.1 + resolution: "rtlcss@npm:4.1.1" dependencies: - find-up: ^5.0.0 + escalade: ^3.1.1 picocolors: ^1.0.0 - postcss: ^8.3.11 + postcss: ^8.4.21 strip-json-comments: ^3.1.1 bin: rtlcss: bin/rtlcss.js - checksum: a3763cad2cb58ce1b950de155097c3c294e7aefc8bf328b58d0cc8d5efb88bf800865edc158a78ace6d1f7f99fea6fd66fb4a354d859b172dadd3dab3e0027b3 + checksum: dcf37d76265b5c84d610488afa68a2506d008f95feac968b35ccae9aa49e7019ae0336a80363303f8f8bbf60df3ecdeb60413548b049114a24748319b68aefde languageName: node linkType: hard @@ -15190,13 +17222,12 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.20.2": - version: 0.20.2 - resolution: "scheduler@npm:0.20.2" +"scheduler@npm:^0.23.0": + version: 0.23.0 + resolution: "scheduler@npm:0.23.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: c4b35cf967c8f0d3e65753252d0f260271f81a81e427241295c5a7b783abf4ea9e905f22f815ab66676f5313be0a25f47be582254db8f9241b259213e999b8fc + checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a languageName: node linkType: hard @@ -15282,11 +17313,12 @@ __metadata: linkType: hard "selfsigned@npm:^2.1.1": - version: 2.1.1 - resolution: "selfsigned@npm:2.1.1" + version: 2.4.1 + resolution: "selfsigned@npm:2.4.1" dependencies: + "@types/node-forge": ^1.3.0 node-forge: ^1 - checksum: aa9ce2150a54838978d5c0aee54d7ebe77649a32e4e690eb91775f71fdff773874a4fbafd0ac73d8ec3b702ff8a395c604df4f8e8868528f36fd6c15076fb43a + checksum: 38b91c56f1d7949c0b77f9bbe4545b19518475cae15e7d7f0043f87b1626710b011ce89879a88969651f650a19d213bb15b7d5b4c2877df9eeeff7ba8f8b9bfa languageName: node linkType: hard @@ -15299,6 +17331,15 @@ __metadata: languageName: node linkType: hard +"semver-diff@npm:^4.0.0": + version: 4.0.0 + resolution: "semver-diff@npm:4.0.0" + dependencies: + semver: ^7.3.5 + checksum: 4a958d6f76c7e7858268e1e2cf936712542441c9e003e561b574167279eee0a9bd55cc7eae1bfb31d3e7ad06a9fc370e7dd412fcfefec8c0daf1ce5aea623559 + languageName: node + linkType: hard + "semver@npm:^5.4.1, semver@npm:^5.5.0": version: 5.7.2 resolution: "semver@npm:5.7.2" @@ -15349,15 +17390,6 @@ __metadata: languageName: node linkType: hard -"serialize-error@npm:^7.0.1": - version: 7.0.1 - resolution: "serialize-error@npm:7.0.1" - dependencies: - type-fest: ^0.13.1 - checksum: e0aba4dca2fc9fe74ae1baf38dbd99190e1945445a241ba646290f2176cdb2032281a76443b02ccf0caf30da5657d510746506368889a593b9835a497fc0732e - languageName: node - linkType: hard - "serialize-javascript@npm:6.0.0": version: 6.0.0 resolution: "serialize-javascript@npm:6.0.0" @@ -15376,7 +17408,7 @@ __metadata: languageName: node linkType: hard -"serve-handler@npm:^6.1.3": +"serve-handler@npm:6.1.5, serve-handler@npm:^6.1.3, serve-handler@npm:^6.1.5": version: 6.1.5 resolution: "serve-handler@npm:6.1.5" dependencies: @@ -15419,10 +17451,36 @@ __metadata: languageName: node linkType: hard -"set-blocking@npm:^2.0.0": - version: 2.0.0 - resolution: "set-blocking@npm:2.0.0" - checksum: 6e65a05f7cf7ebdf8b7c75b101e18c0b7e3dff4940d480efed8aad3a36a4005140b660fa1d804cb8bce911cac290441dc728084a30504d3516ac2ff7ad607b02 +"serve@npm:^14.2.1": + version: 14.2.1 + resolution: "serve@npm:14.2.1" + dependencies: + "@zeit/schemas": 2.29.0 + ajv: 8.11.0 + arg: 5.0.2 + boxen: 7.0.0 + chalk: 5.0.1 + chalk-template: 0.4.0 + clipboardy: 3.0.0 + compression: 1.7.4 + is-port-reachable: 4.0.0 + serve-handler: 6.1.5 + update-check: 1.5.4 + bin: + serve: build/main.js + checksum: c39a517b5d795a0a5c2f9fb9ff088b7e4962c579e34ace5b85dd62f93e0eacbc8a90359792c153c444a83258ffda392113dff7bfd10d41ced574a2d1886c2994 + languageName: node + linkType: hard + +"set-function-length@npm:^1.1.1": + version: 1.1.1 + resolution: "set-function-length@npm:1.1.1" + dependencies: + define-data-property: ^1.1.1 + get-intrinsic: ^1.2.1 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.0 + checksum: c131d7569cd7e110cafdfbfbb0557249b538477624dfac4fc18c376d879672fa52563b74029ca01f8f4583a8acb35bb1e873d573a24edb80d978a7ee607c6e06 languageName: node linkType: hard @@ -15512,14 +17570,14 @@ __metadata: linkType: hard "shiki@npm:^0.14.1": - version: 0.14.5 - resolution: "shiki@npm:0.14.5" + version: 0.14.6 + resolution: "shiki@npm:0.14.6" dependencies: ansi-sequence-parser: ^1.1.0 jsonc-parser: ^3.2.0 vscode-oniguruma: ^1.7.0 vscode-textmate: ^8.0.0 - checksum: 41d847817cfc9bb6d8bf190316896698d250303656546446659cc02caed8dcc171b10cd113bb5da82425b51d0032e87aafcdc36c3dd61dadc123170b438da736 + checksum: 24d9e29f93546118f1c07659e8a38f7dbf57b06479a0a9245e0823f7c988c825be53ad0b83a820e2eda5edbf3f0c6d17fad398b825130de1c11973e0bd7075fc languageName: node linkType: hard @@ -15580,6 +17638,15 @@ __metadata: languageName: node linkType: hard +"skin-tone@npm:^2.0.0": + version: 2.0.0 + resolution: "skin-tone@npm:2.0.0" + dependencies: + unicode-emoji-modifier-base: ^1.0.0 + checksum: 19de157586b8019cacc55eb25d9d640f00fc02415761f3e41a4527142970fd4e7f6af0333bc90e879858766c20a976107bb386ffd4c812289c01d51f2c8d182c + languageName: node + linkType: hard + "slash@npm:^3.0.0": version: 3.0.0 resolution: "slash@npm:3.0.0" @@ -15599,19 +17666,9 @@ __metadata: resolution: "slice-ansi@npm:4.0.0" dependencies: ansi-styles: ^4.0.0 - astral-regex: ^2.0.0 - is-fullwidth-code-point: ^3.0.0 - checksum: 4a82d7f085b0e1b070e004941ada3c40d3818563ac44766cca4ceadd2080427d337554f9f99a13aaeb3b4a94d9964d9466c807b3d7b7541d1ec37ee32d308756 - languageName: node - linkType: hard - -"slice-ansi@npm:^5.0.0": - version: 5.0.0 - resolution: "slice-ansi@npm:5.0.0" - dependencies: - ansi-styles: ^6.0.0 - is-fullwidth-code-point: ^4.0.0 - checksum: 7e600a2a55e333a21ef5214b987c8358fe28bfb03c2867ff2cbf919d62143d1812ac27b4297a077fdaf27a03da3678e49551c93e35f9498a3d90221908a1180e + astral-regex: ^2.0.0 + is-fullwidth-code-point: ^3.0.0 + checksum: 4a82d7f085b0e1b070e004941ada3c40d3818563ac44766cca4ceadd2080427d337554f9f99a13aaeb3b4a94d9964d9466c807b3d7b7541d1ec37ee32d308756 languageName: node linkType: hard @@ -15623,9 +17680,9 @@ __metadata: linkType: hard "smol-toml@npm:^1.1.2": - version: 1.1.2 - resolution: "smol-toml@npm:1.1.2" - checksum: aa984b8d7aadb9c7db601533f81bcc0e7b6773fe56b69e87fb06224ac0c22702900b927becf0f5af0250b29746648344b57ecbcc203e82d667d46a19e1a61d77 + version: 1.1.3 + resolution: "smol-toml@npm:1.1.3" + checksum: 7948c0823b3d8db9ebf7d6dc706f75ea2bc55fa0233e6fccabc2ae3be0f1410da4617d9e3db0708a6434cfd35e13c2bc453300fa4ab11dde3da5df1c166feb39 languageName: node linkType: hard @@ -15640,18 +17697,18 @@ __metadata: languageName: node linkType: hard -"socks-proxy-agent@npm:^7.0.0": - version: 7.0.0 - resolution: "socks-proxy-agent@npm:7.0.0" +"socks-proxy-agent@npm:^8.0.1": + version: 8.0.2 + resolution: "socks-proxy-agent@npm:8.0.2" dependencies: - agent-base: ^6.0.2 - debug: ^4.3.3 - socks: ^2.6.2 - checksum: 720554370154cbc979e2e9ce6a6ec6ced205d02757d8f5d93fe95adae454fc187a5cbfc6b022afab850a5ce9b4c7d73e0f98e381879cf45f66317a4895953846 + agent-base: ^7.0.2 + debug: ^4.3.4 + socks: ^2.7.1 + checksum: 4fb165df08f1f380881dcd887b3cdfdc1aba3797c76c1e9f51d29048be6e494c5b06d68e7aea2e23df4572428f27a3ec22b3d7c75c570c5346507433899a4b6d languageName: node linkType: hard -"socks@npm:^2.6.2": +"socks@npm:^2.7.1": version: 2.7.1 resolution: "socks@npm:2.7.1" dependencies: @@ -15718,7 +17775,7 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.7.3": +"source-map@npm:^0.7.0, source-map@npm:^0.7.3": version: 0.7.4 resolution: "source-map@npm:0.7.4" checksum: 01cc5a74b1f0e1d626a58d36ad6898ea820567e87f18dfc9d24a9843a351aaa2ec09b87422589906d6ff1deed29693e176194dc88bcae7c9a852dc74b311dbf5 @@ -15732,6 +17789,13 @@ __metadata: languageName: node linkType: hard +"space-separated-tokens@npm:^2.0.0": + version: 2.0.2 + resolution: "space-separated-tokens@npm:2.0.2" + checksum: 202e97d7ca1ba0758a0aa4fe226ff98142073bcceeff2da3aad037968878552c3bbce3b3231970025375bbba5aee00c5b8206eda408da837ab2dc9c0f26be990 + languageName: node + linkType: hard + "spdy-transport@npm:^3.0.0": version: 3.0.0 resolution: "spdy-transport@npm:3.0.0" @@ -15775,6 +17839,13 @@ __metadata: languageName: node linkType: hard +"srcset@npm:^4.0.0": + version: 4.0.0 + resolution: "srcset@npm:4.0.0" + checksum: aceb898c9281101ef43bfbf96bf04dfae828e1bf942a45df6fad74ae9f8f0a425f4bca1480e0d22879beb40dd2bc6947e0e1e5f4d307a714666196164bc5769d + languageName: node + linkType: hard + "ssri@npm:^10.0.0": version: 10.0.5 resolution: "ssri@npm:10.0.5" @@ -15791,15 +17862,6 @@ __metadata: languageName: node linkType: hard -"stack-utils@npm:^2.0.6": - version: 2.0.6 - resolution: "stack-utils@npm:2.0.6" - dependencies: - escape-string-regexp: ^2.0.0 - checksum: 052bf4d25bbf5f78e06c1d5e67de2e088b06871fa04107ca8d3f0e9d9263326e2942c8bedee3545795fc77d787d443a538345eef74db2f8e35db3558c6f91ff7 - languageName: node - linkType: hard - "stacktrace-parser@npm:^0.1.10": version: 0.1.10 resolution: "stacktrace-parser@npm:0.1.10" @@ -15809,6 +17871,13 @@ __metadata: languageName: node linkType: hard +"state-local@npm:^1.0.6": + version: 1.0.7 + resolution: "state-local@npm:1.0.7" + checksum: d1afcf1429e7e6eb08685b3a94be8797db847369316d4776fd51f3962b15b984dacc7f8e401ad20968e5798c9565b4b377afedf4e4c4d60fe7495e1cbe14a251 + languageName: node + linkType: hard + "state-toggle@npm:^1.0.0": version: 1.0.3 resolution: "state-toggle@npm:1.0.3" @@ -15831,9 +17900,9 @@ __metadata: linkType: hard "std-env@npm:^3.0.1": - version: 3.4.3 - resolution: "std-env@npm:3.4.3" - checksum: bef186fb2baddda31911234b1e58fa18f181eb6930616aaec3b54f6d5db65f2da5daaa5f3b326b98445a7d50ca81d6fe8809ab4ebab85ecbe4a802f1b40921bf + version: 3.6.0 + resolution: "std-env@npm:3.6.0" + checksum: ec344e93af17fd1b71eb28aeb4712f72790b9f2363981fc91ad1a91c9c7967c1ab89271819242d1b3bdbd57f10ac8ef0559d561ccf081a5377f9b3cd8c9b2259 languageName: node linkType: hard @@ -15869,7 +17938,7 @@ __metadata: languageName: node linkType: hard -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.0.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2, string-width@npm:^4.2.3": +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.0.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2, string-width@npm:^4.2.3": version: 4.2.3 resolution: "string-width@npm:4.2.3" dependencies: @@ -15880,7 +17949,7 @@ __metadata: languageName: node linkType: hard -"string-width@npm:^5.0.0, string-width@npm:^5.0.1, string-width@npm:^5.1.2": +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": version: 5.1.2 resolution: "string-width@npm:5.1.2" dependencies: @@ -15909,6 +17978,16 @@ __metadata: languageName: node linkType: hard +"stringify-entities@npm:^4.0.0": + version: 4.0.3 + resolution: "stringify-entities@npm:4.0.3" + dependencies: + character-entities-html4: ^2.0.0 + character-entities-legacy: ^3.0.0 + checksum: 59e8f523b403bf7d415690e72ae52982decd6ea5426bd8b3f5c66225ddde73e766c0c0d91627df082d0794e30b19dd907ffb5864cef3602e4098d6777d7ca3c2 + languageName: node + linkType: hard + "stringify-object@npm:^3.3.0": version: 3.3.0 resolution: "stringify-object@npm:3.3.0" @@ -15991,6 +18070,24 @@ __metadata: languageName: node linkType: hard +"style-to-object@npm:^0.4.0": + version: 0.4.4 + resolution: "style-to-object@npm:0.4.4" + dependencies: + inline-style-parser: 0.1.1 + checksum: 41656c06f93ac0a7ac260ebc2f9d09a8bd74b8ec1836f358cc58e169235835a3a356977891d2ebbd76f0e08a53616929069199f9cce543214d3dc98346e19c9a + languageName: node + linkType: hard + +"style-to-object@npm:^1.0.0": + version: 1.0.5 + resolution: "style-to-object@npm:1.0.5" + dependencies: + inline-style-parser: 0.2.2 + checksum: 6201063204b6a94645f81b189452b2ca3e63d61867ec48523f4d52609c81e96176739fa12020d97fbbf023efb57a6f7ec3a15fb3a7fb7eb3ffea0b52b9dd6b8c + languageName: node + linkType: hard + "stylehacks@npm:^5.1.1": version: 5.1.1 resolution: "stylehacks@npm:5.1.1" @@ -16010,18 +18107,6 @@ __metadata: languageName: node linkType: hard -"supertap@npm:^3.0.1": - version: 3.0.1 - resolution: "supertap@npm:3.0.1" - dependencies: - indent-string: ^5.0.0 - js-yaml: ^3.14.1 - serialize-error: ^7.0.1 - strip-ansi: ^7.0.1 - checksum: ee3d71c1d25f7f15d4a849e72b0c5f430df7cd8f702cf082fdbec5642a9546be6557766745655fa3a3e9c88f7c7eed849f2d74457b5b72cb9d94a779c0c8a948 - languageName: node - linkType: hard - "supports-color@npm:8.1.1, supports-color@npm:^8.0.0": version: 8.1.1 resolution: "supports-color@npm:8.1.1" @@ -16081,12 +18166,12 @@ __metadata: linkType: hard "synckit@npm:^0.8.5": - version: 0.8.5 - resolution: "synckit@npm:0.8.5" + version: 0.8.6 + resolution: "synckit@npm:0.8.6" dependencies: - "@pkgr/utils": ^2.3.1 - tslib: ^2.5.0 - checksum: 8a9560e5d8f3d94dc3cf5f7b9c83490ffa30d320093560a37b88f59483040771fd1750e76b9939abfbb1b5a23fd6dfbae77f6b338abffe7cae7329cd9b9bb86b + "@pkgr/utils": ^2.4.2 + tslib: ^2.6.2 + checksum: 7c1f4991d0afd63c090c0537f1cf8619dd5777a40cf83bf46beadbf4eb0f9e400d92044e90a177a305df4bcb56efbaf1b689877f301f2672d865b6eecf1be75a languageName: node linkType: hard @@ -16172,14 +18257,7 @@ __metadata: languageName: node linkType: hard -"temp-dir@npm:^3.0.0": - version: 3.0.0 - resolution: "temp-dir@npm:3.0.0" - checksum: 577211e995d1d584dd60f1469351d45e8a5b4524e4a9e42d3bdd12cfde1d0bb8f5898311bef24e02aaafb69514c1feb58c7b4c33dcec7129da3b0861a4ca935b - languageName: node - linkType: hard - -"terser-webpack-plugin@npm:^5.3.3, terser-webpack-plugin@npm:^5.3.7": +"terser-webpack-plugin@npm:^5.3.3, terser-webpack-plugin@npm:^5.3.7, terser-webpack-plugin@npm:^5.3.9": version: 5.3.9 resolution: "terser-webpack-plugin@npm:5.3.9" dependencies: @@ -16201,9 +18279,9 @@ __metadata: languageName: node linkType: hard -"terser@npm:^5.10.0, terser@npm:^5.16.8": - version: 5.21.0 - resolution: "terser@npm:5.21.0" +"terser@npm:^5.10.0, terser@npm:^5.15.1, terser@npm:^5.16.8": + version: 5.26.0 + resolution: "terser@npm:5.26.0" dependencies: "@jridgewell/source-map": ^0.3.3 acorn: ^8.8.2 @@ -16211,7 +18289,7 @@ __metadata: source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: 130f1567af1ffa4ddb067651bb284a01b45b5c83e82b3a072a5ff94b0b00ac35090f89c8714631a4a45972f65187bc149fc7144380611f437e1e3d9e174b136b + checksum: 02a9bb896f04df828025af8f0eced36c315d25d310b6c2418e7dad2bed19ddeb34a9cea9b34e7c24789830fa51e1b6a9be26679980987a9c817a7e6d9cd4154b languageName: node linkType: hard @@ -16236,13 +18314,6 @@ __metadata: languageName: node linkType: hard -"time-zone@npm:^1.0.0": - version: 1.0.0 - resolution: "time-zone@npm:1.0.0" - checksum: e46f5a69b8c236dcd8e91e29d40d4e7a3495ed4f59888c3f84ce1d9678e20461421a6ba41233509d47dd94bc18f1a4377764838b21b584663f942b3426dcbce8 - languageName: node - linkType: hard - "tiny-invariant@npm:^1.0.2": version: 1.3.1 resolution: "tiny-invariant@npm:1.3.1" @@ -16333,6 +18404,13 @@ __metadata: languageName: node linkType: hard +"trim-lines@npm:^3.0.0": + version: 3.0.1 + resolution: "trim-lines@npm:3.0.1" + checksum: e241da104682a0e0d807222cc1496b92e716af4db7a002f4aeff33ae6a0024fef93165d49eab11aa07c71e1347c42d46563f91dfaa4d3fb945aa535cdead53ed + languageName: node + linkType: hard + "trim-trailing-lines@npm:^1.0.0": version: 1.1.4 resolution: "trim-trailing-lines@npm:1.1.4" @@ -16354,6 +18432,13 @@ __metadata: languageName: node linkType: hard +"trough@npm:^2.0.0": + version: 2.1.0 + resolution: "trough@npm:2.1.0" + checksum: a577bb561c2b401cc0e1d9e188fcfcdf63b09b151ff56a668da12197fe97cac15e3d77d5b51f426ccfd94255744a9118e9e9935afe81a3644fa1be9783c82886 + languageName: node + linkType: hard + "ts-api-utils@npm:^1.0.1": version: 1.0.3 resolution: "ts-api-utils@npm:1.0.3" @@ -16378,8 +18463,8 @@ __metadata: linkType: hard "ts-node@npm:^10.9.1": - version: 10.9.1 - resolution: "ts-node@npm:10.9.1" + version: 10.9.2 + resolution: "ts-node@npm:10.9.2" dependencies: "@cspotcode/source-map-support": ^0.8.0 "@tsconfig/node10": ^1.0.7 @@ -16411,7 +18496,7 @@ __metadata: ts-node-script: dist/bin-script.js ts-node-transpile-only: dist/bin-transpile.js ts-script: dist/bin-script-deprecated.js - checksum: 090adff1302ab20bd3486e6b4799e90f97726ed39e02b39e566f8ab674fd5bd5f727f43615debbfc580d33c6d9d1c6b1b3ce7d8e3cca3e20530a145ffa232c35 + checksum: fde256c9073969e234526e2cfead42591b9a2aec5222bac154b0de2fa9e4ceb30efcd717ee8bc785a56f3a119bdd5aa27b333d9dbec94ed254bd26f8944c67ac languageName: node linkType: hard @@ -16451,7 +18536,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.0": +"tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.0, tslib@npm:^2.6.2": version: 2.6.2 resolution: "tslib@npm:2.6.2" checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad @@ -16479,6 +18564,22 @@ __metadata: languageName: node linkType: hard +"tsx@npm:^4.6.2": + version: 4.6.2 + resolution: "tsx@npm:4.6.2" + dependencies: + esbuild: ~0.18.20 + fsevents: ~2.3.3 + get-tsconfig: ^4.7.2 + dependenciesMeta: + fsevents: + optional: true + bin: + tsx: dist/cli.mjs + checksum: a9f13bdb67bfb316bbfc92303d8464323ab1b673aa93ea97271c211a8ba7c59274d4b32eeec5ad8fbd0b04260a092a3ad2116abeb6913254ba456010ff685743 + languageName: node + linkType: hard + "tweetnacl-util@npm:^0.15.1": version: 0.15.1 resolution: "tweetnacl-util@npm:0.15.1" @@ -16502,20 +18603,13 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:^4.0.0, type-detect@npm:^4.0.5": +"type-detect@npm:^4.0.0, type-detect@npm:^4.0.8": version: 4.0.8 resolution: "type-detect@npm:4.0.8" checksum: 62b5628bff67c0eb0b66afa371bd73e230399a8d2ad30d852716efcc4656a7516904570cd8631a49a3ce57c10225adf5d0cbdcb47f6b0255fe6557c453925a15 languageName: node linkType: hard -"type-fest@npm:^0.13.1": - version: 0.13.1 - resolution: "type-fest@npm:0.13.1" - checksum: e6bf2e3c449f27d4ef5d56faf8b86feafbc3aec3025fc9a5fbe2db0a2587c44714521f9c30d8516a833c8c506d6263f5cc11267522b10c6ccdb6cc55b0a9d1c4 - languageName: node - linkType: hard - "type-fest@npm:^0.20.2": version: 0.20.2 resolution: "type-fest@npm:0.20.2" @@ -16537,7 +18631,14 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^2.5.0": +"type-fest@npm:^1.0.1": + version: 1.4.0 + resolution: "type-fest@npm:1.4.0" + checksum: b011c3388665b097ae6a109a437a04d6f61d81b7357f74cbcb02246f2f5bd72b888ae33631b99871388122ba0a87f4ff1c94078e7119ff22c70e52c0ff828201 + languageName: node + linkType: hard + +"type-fest@npm:^2.13.0, type-fest@npm:^2.5.0": version: 2.19.0 resolution: "type-fest@npm:2.19.0" checksum: a4ef07ece297c9fba78fc1bd6d85dff4472fe043ede98bd4710d2615d15776902b595abf62bd78339ed6278f021235fb28a96361f8be86ed754f778973a0d278 @@ -16591,28 +18692,18 @@ __metadata: linkType: hard "typedoc@npm:^0.25.0": - version: 0.25.2 - resolution: "typedoc@npm:0.25.2" + version: 0.25.4 + resolution: "typedoc@npm:0.25.4" dependencies: lunr: ^2.3.9 marked: ^4.3.0 minimatch: ^9.0.3 shiki: ^0.14.1 peerDependencies: - typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x + typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x bin: typedoc: bin/typedoc - checksum: 5b6e24bae7498bb542aaba495378ed5a3e13c76eb04a1ae95b506f76bda4d517847101fb05a7eab3f6b79357d1e2ac6f4747d39792395329b72e463f7effda65 - languageName: node - linkType: hard - -"typescript@npm:4.9.4": - version: 4.9.4 - resolution: "typescript@npm:4.9.4" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: e782fb9e0031cb258a80000f6c13530288c6d63f1177ed43f770533fdc15740d271554cdae86701c1dd2c83b082cea808b07e97fd68b38a172a83dbf9e0d0ef9 + checksum: 6d441baa277c0db4d577db2932a7af316d175415841e2faf2e68e3eda6ad60356c54f56374f89c5233d7bd5c057b0337455e5d484d8463e1445e67c37a6d94eb languageName: node linkType: hard @@ -16627,22 +18718,22 @@ __metadata: linkType: hard "typescript@npm:^5.0.4, typescript@npm:^5.2.2": - version: 5.2.2 - resolution: "typescript@npm:5.2.2" + version: 5.3.3 + resolution: "typescript@npm:5.3.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 7912821dac4d962d315c36800fe387cdc0a6298dba7ec171b350b4a6e988b51d7b8f051317786db1094bd7431d526b648aba7da8236607febb26cf5b871d2d3c + checksum: 2007ccb6e51bbbf6fde0a78099efe04dc1c3dfbdff04ca3b6a8bc717991862b39fd6126c0c3ebf2d2d98ac5e960bcaa873826bb2bb241f14277034148f41f6a2 languageName: node linkType: hard -"typescript@patch:typescript@4.9.4#~builtin": - version: 4.9.4 - resolution: "typescript@patch:typescript@npm%3A4.9.4#~builtin::version=4.9.4&hash=289587" +"typescript@npm:~5.2.2": + version: 5.2.2 + resolution: "typescript@npm:5.2.2" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 2160f7ad975c59b2f5816817d3916be1d156c5688a7517602b3b640c5015e740f4ba933996ac85371d68f7bbdd41602150fb8b68334122ac637fdb5418085e7a + checksum: 7912821dac4d962d315c36800fe387cdc0a6298dba7ec171b350b4a6e988b51d7b8f051317786db1094bd7431d526b648aba7da8236607febb26cf5b871d2d3c languageName: node linkType: hard @@ -16657,6 +18748,16 @@ __metadata: linkType: hard "typescript@patch:typescript@^5.0.4#~builtin, typescript@patch:typescript@^5.2.2#~builtin": + version: 5.3.3 + resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=f3b441" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: f61375590b3162599f0f0d5b8737877ac0a7bc52761dbb585d67e7b8753a3a4c42d9a554c4cc929f591ffcf3a2b0602f65ae3ce74714fd5652623a816862b610 + languageName: node + linkType: hard + +"typescript@patch:typescript@~5.2.2#~builtin": version: 5.2.2 resolution: "typescript@patch:typescript@npm%3A5.2.2#~builtin::version=5.2.2&hash=f3b441" bin: @@ -16687,10 +18788,10 @@ __metadata: languageName: node linkType: hard -"ua-parser-js@npm:^1.0.33, ua-parser-js@npm:^1.0.35": - version: 1.0.36 - resolution: "ua-parser-js@npm:1.0.36" - checksum: 5b2c8a5e3443dfbba7624421805de946457c26ae167cb2275781a2729d1518f7067c9d5c74c3b0acac4b9ff3278cae4eace08ca6eecb63848bc3b2f6a63cc975 +"ua-parser-js@npm:^1.0.33": + version: 1.0.37 + resolution: "ua-parser-js@npm:1.0.37" + checksum: 4d481c720d523366d7762dc8a46a1b58967d979aacf786f9ceceb1cd767de069f64a4bdffb63956294f1c0696eb465ddb950f28ba90571709e33521b4bd75e07 languageName: node linkType: hard @@ -16704,12 +18805,19 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 + languageName: node + linkType: hard + "undici@npm:^5.14.0": - version: 5.25.3 - resolution: "undici@npm:5.25.3" + version: 5.28.2 + resolution: "undici@npm:5.28.2" dependencies: "@fastify/busboy": ^2.0.0 - checksum: 65b814b7d8b06dab2d41c250d123663fe94edb78cf1a891cf3476569ea66dc425c7d4ba52b91d6f8ed6eba24613dd28e4a5070c372063532c3b997cd343ccc96 + checksum: f9e9335803f962fff07c3c11c6d50bbc76248bacf97035047155adb29c3622a65bd6bff23a22218189740133149d22e63b68131d8c40e78ac6cb4b6d686a6dfa languageName: node linkType: hard @@ -16730,6 +18838,13 @@ __metadata: languageName: node linkType: hard +"unicode-emoji-modifier-base@npm:^1.0.0": + version: 1.0.0 + resolution: "unicode-emoji-modifier-base@npm:1.0.0" + checksum: 6e1521d35fa69493207eb8b41f8edb95985d8b3faf07c01d820a1830b5e8403e20002563e2f84683e8e962a49beccae789f0879356bf92a4ec7a4dd8e2d16fdb + languageName: node + linkType: hard + "unicode-match-property-ecmascript@npm:^2.0.0": version: 2.0.0 resolution: "unicode-match-property-ecmascript@npm:2.0.0" @@ -16768,7 +18883,22 @@ __metadata: languageName: node linkType: hard -"unified@npm:^9.0.0, unified@npm:^9.2.2": +"unified@npm:^11.0.0, unified@npm:^11.0.3, unified@npm:^11.0.4": + version: 11.0.4 + resolution: "unified@npm:11.0.4" + dependencies: + "@types/unist": ^3.0.0 + bail: ^2.0.0 + devlop: ^1.0.0 + extend: ^3.0.0 + is-plain-obj: ^4.0.0 + trough: ^2.0.0 + vfile: ^6.0.0 + checksum: cfb023913480ac2bd5e787ffb8c27782c43e6be4a55f8f1c288233fce46a7ebe7718ccc5adb80bf8d56b7ef85f5fc32239c7bfccda006f9f2382e0cc2e2a77e4 + languageName: node + linkType: hard + +"unified@npm:^9.2.2": version: 9.2.2 resolution: "unified@npm:9.2.2" dependencies: @@ -16809,6 +18939,15 @@ __metadata: languageName: node linkType: hard +"unique-string@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-string@npm:3.0.0" + dependencies: + crypto-random-string: ^4.0.0 + checksum: 1a1e2e7d02eab1bb10f720475da735e1990c8a5ff34edd1a3b6bc31590cb4210b7a1233d779360cc622ce11c211e43afa1628dd658f35d3e6a89964b622940df + languageName: node + linkType: hard + "unist-builder@npm:2.0.3, unist-builder@npm:^2.0.0": version: 2.0.3 resolution: "unist-builder@npm:2.0.3" @@ -16816,12 +18955,13 @@ __metadata: languageName: node linkType: hard -"unist-util-find-after@npm:^3.0.0": - version: 3.0.0 - resolution: "unist-util-find-after@npm:3.0.0" +"unist-util-find-after@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-find-after@npm:5.0.0" dependencies: - unist-util-is: ^4.0.0 - checksum: daa9a28f6cdf533a72ce7ec4864dbe0f11f0fd3efd337b54c08a8a9a47cdc8d10a299cd984d7f512a57e97af012df052210a51aab7c9afd6b1e24da3b2d0a714 + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + checksum: e64bd5ebee7ac021cf990bf33e9ec29fc6452159187d4a7fa0f77334bea8e378fea7a7fb0bcf957300b2ffdba902ff25b62c165fc8b86309613da35ad793ada0 languageName: node linkType: hard @@ -16839,6 +18979,24 @@ __metadata: languageName: node linkType: hard +"unist-util-is@npm:^6.0.0": + version: 6.0.0 + resolution: "unist-util-is@npm:6.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: f630a925126594af9993b091cf807b86811371e465b5049a6283e08537d3e6ba0f7e248e1e7dab52cfe33f9002606acef093441137181b327f6fe504884b20e2 + languageName: node + linkType: hard + +"unist-util-position-from-estree@npm:^2.0.0": + version: 2.0.0 + resolution: "unist-util-position-from-estree@npm:2.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: d3b3048a5727c2367f64ef6dcc5b20c4717215ef8b1372ff9a7c426297c5d1e5776409938acd01531213e2cd2543218d16e73f9f862f318e9496e2c73bb18354 + languageName: node + linkType: hard + "unist-util-position@npm:^3.0.0": version: 3.1.0 resolution: "unist-util-position@npm:3.1.0" @@ -16846,6 +19004,15 @@ __metadata: languageName: node linkType: hard +"unist-util-position@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-position@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: f89b27989b19f07878de9579cd8db2aa0194c8360db69e2c99bd2124a480d79c08f04b73a64daf01a8fb3af7cba65ff4b45a0b978ca243226084ad5f5d441dde + languageName: node + linkType: hard + "unist-util-remove-position@npm:^2.0.0": version: 2.0.1 resolution: "unist-util-remove-position@npm:2.0.1" @@ -16855,6 +19022,16 @@ __metadata: languageName: node linkType: hard +"unist-util-remove-position@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-remove-position@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + unist-util-visit: ^5.0.0 + checksum: 8aabdb9d0e3e744141bc123d8f87b90835d521209ad3c6c4619d403b324537152f0b8f20dda839b40c3aa0abfbf1828b3635a7a8bb159c3ed469e743023510ee + languageName: node + linkType: hard + "unist-util-remove@npm:^2.0.0": version: 2.1.0 resolution: "unist-util-remove@npm:2.1.0" @@ -16873,6 +19050,15 @@ __metadata: languageName: node linkType: hard +"unist-util-stringify-position@npm:^4.0.0": + version: 4.0.0 + resolution: "unist-util-stringify-position@npm:4.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: e2e7aee4b92ddb64d314b4ac89eef7a46e4c829cbd3ee4aee516d100772b490eb6b4974f653ba0717a0071ca6ea0770bf22b0a2ea62c65fcba1d071285e96324 + languageName: node + linkType: hard + "unist-util-visit-parents@npm:^3.0.0": version: 3.1.1 resolution: "unist-util-visit-parents@npm:3.1.1" @@ -16883,6 +19069,16 @@ __metadata: languageName: node linkType: hard +"unist-util-visit-parents@npm:^6.0.0": + version: 6.0.1 + resolution: "unist-util-visit-parents@npm:6.0.1" + dependencies: + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + checksum: 08927647c579f63b91aafcbec9966dc4a7d0af1e5e26fc69f4e3e6a01215084835a2321b06f3cbe7bf7914a852830fc1439f0fc3d7153d8804ac3ef851ddfa20 + languageName: node + linkType: hard + "unist-util-visit@npm:2.0.3, unist-util-visit@npm:^2.0.0, unist-util-visit@npm:^2.0.3": version: 2.0.3 resolution: "unist-util-visit@npm:2.0.3" @@ -16894,6 +19090,17 @@ __metadata: languageName: node linkType: hard +"unist-util-visit@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-visit@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + unist-util-visit-parents: ^6.0.0 + checksum: 9ec42e618e7e5d0202f3c191cd30791b51641285732767ee2e6bcd035931032e3c1b29093f4d7fd0c79175bbc1f26f24f26ee49770d32be76f8730a652a857e6 + languageName: node + linkType: hard + "universalify@npm:^0.1.0": version: 0.1.2 resolution: "universalify@npm:0.1.2" @@ -16902,9 +19109,9 @@ __metadata: linkType: hard "universalify@npm:^2.0.0": - version: 2.0.0 - resolution: "universalify@npm:2.0.0" - checksum: 2406a4edf4a8830aa6813278bab1f953a8e40f2f63a37873ffa9a3bc8f9745d06cc8e88f3572cb899b7e509013f7f6fcc3e37e8a6d914167a5381d8440518c44 + version: 2.0.1 + resolution: "universalify@npm:2.0.1" + checksum: ecd8469fe0db28e7de9e5289d32bd1b6ba8f7183db34f3bfc4ca53c49891c2d6aa05f3fb3936a81285a905cc509fb641a0c3fc131ec786167eff41236ae32e60 languageName: node linkType: hard @@ -16936,6 +19143,16 @@ __metadata: languageName: node linkType: hard +"update-check@npm:1.5.4": + version: 1.5.4 + resolution: "update-check@npm:1.5.4" + dependencies: + registry-auth-token: 3.3.2 + registry-url: 3.1.0 + checksum: 2c9f7de6f030364c5ea02a341e5ae2dfe76da6559b32d40dd3b047b3ac0927408cf92d322c51cd8e009688210a85ccbf1eba449762a65a0d1b14f3cdf1ea5c48 + languageName: node + linkType: hard + "update-notifier@npm:^5.1.0": version: 5.1.0 resolution: "update-notifier@npm:5.1.0" @@ -16958,6 +19175,28 @@ __metadata: languageName: node linkType: hard +"update-notifier@npm:^6.0.2": + version: 6.0.2 + resolution: "update-notifier@npm:6.0.2" + dependencies: + boxen: ^7.0.0 + chalk: ^5.0.1 + configstore: ^6.0.0 + has-yarn: ^3.0.0 + import-lazy: ^4.0.0 + is-ci: ^3.0.1 + is-installed-globally: ^0.4.0 + is-npm: ^6.0.0 + is-yarn-global: ^0.4.0 + latest-version: ^7.0.0 + pupa: ^3.1.0 + semver: ^7.3.7 + semver-diff: ^4.0.0 + xdg-basedir: ^5.1.0 + checksum: 4bae7b3eca7b2068b6b87dde88c9dad24831fa913a5b83ecb39a7e4702c93e8b05fd9bcac5f1a005178f6e5dc859e0b3817ddda833d2a7ab92c6485e078b3cc8 + languageName: node + linkType: hard + "uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" @@ -16993,50 +19232,6 @@ __metadata: languageName: node linkType: hard -"use-composed-ref@npm:^1.3.0": - version: 1.3.0 - resolution: "use-composed-ref@npm:1.3.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: f771cbadfdc91e03b7ab9eb32d0fc0cc647755711801bf507e891ad38c4bbc5f02b2509acadf9c965ec9c5f2f642fd33bdfdfb17b0873c4ad0a9b1f5e5e724bf - languageName: node - linkType: hard - -"use-isomorphic-layout-effect@npm:^1.1.1": - version: 1.1.2 - resolution: "use-isomorphic-layout-effect@npm:1.1.2" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: a6532f7fc9ae222c3725ff0308aaf1f1ddbd3c00d685ef9eee6714fd0684de5cb9741b432fbf51e61a784e2955424864f7ea9f99734a02f237b17ad3e18ea5cb - languageName: node - linkType: hard - -"use-latest@npm:^1.2.1": - version: 1.2.1 - resolution: "use-latest@npm:1.2.1" - dependencies: - use-isomorphic-layout-effect: ^1.1.1 - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: ed3f2ddddf6f21825e2ede4c2e0f0db8dcce5129802b69d1f0575fc1b42380436e8c76a6cd885d4e9aa8e292e60fb8b959c955f33c6a9123b83814a1a1875367 - languageName: node - linkType: hard - -"use-sync-external-store@npm:^1.2.0": - version: 1.2.0 - resolution: "use-sync-external-store@npm:1.2.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 5c639e0f8da3521d605f59ce5be9e094ca772bd44a4ce7322b055a6f58eeed8dda3c94cabd90c7a41fb6fa852210092008afe48f7038792fd47501f33299116a - languageName: node - linkType: hard - "util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -17096,13 +19291,13 @@ __metadata: linkType: hard "v8-to-istanbul@npm:^9.0.1": - version: 9.1.0 - resolution: "v8-to-istanbul@npm:9.1.0" + version: 9.2.0 + resolution: "v8-to-istanbul@npm:9.2.0" dependencies: "@jridgewell/trace-mapping": ^0.3.12 "@types/istanbul-lib-coverage": ^2.0.1 - convert-source-map: ^1.6.0 - checksum: 2069d59ee46cf8d83b4adfd8a5c1a90834caffa9f675e4360f1157ffc8578ef0f763c8f32d128334424159bb6b01f3876acd39cd13297b2769405a9da241f8d1 + convert-source-map: ^2.0.0 + checksum: 31ef98c6a31b1dab6be024cf914f235408cd4c0dc56a5c744a5eea1a9e019ba279e1b6f90d695b78c3186feed391ed492380ccf095009e2eb91f3d058f0b4491 languageName: node linkType: hard @@ -17127,6 +19322,16 @@ __metadata: languageName: node linkType: hard +"vfile-location@npm:^5.0.0": + version: 5.0.2 + resolution: "vfile-location@npm:5.0.2" + dependencies: + "@types/unist": ^3.0.0 + vfile: ^6.0.0 + checksum: b61c048cedad3555b4f007f390412c6503f58a6a130b58badf4ee340c87e0d7421e9c86bbc1494c57dedfccadb60f5176cc60ba3098209d99fb3a3d8804e4c38 + languageName: node + linkType: hard + "vfile-message@npm:^2.0.0": version: 2.0.4 resolution: "vfile-message@npm:2.0.4" @@ -17137,6 +19342,16 @@ __metadata: languageName: node linkType: hard +"vfile-message@npm:^4.0.0": + version: 4.0.2 + resolution: "vfile-message@npm:4.0.2" + dependencies: + "@types/unist": ^3.0.0 + unist-util-stringify-position: ^4.0.0 + checksum: 964e7e119f4c0e0270fc269119c41c96da20afa01acb7c9809a88365c8e0c64aa692fafbd952669382b978002ecd7ad31ef4446d85e8a22cdb62f6df20186c2d + languageName: node + linkType: hard + "vfile@npm:^4.0.0": version: 4.2.1 resolution: "vfile@npm:4.2.1" @@ -17149,6 +19364,17 @@ __metadata: languageName: node linkType: hard +"vfile@npm:^6.0.0, vfile@npm:^6.0.1": + version: 6.0.1 + resolution: "vfile@npm:6.0.1" + dependencies: + "@types/unist": ^3.0.0 + unist-util-stringify-position: ^4.0.0 + vfile-message: ^4.0.0 + checksum: 05ccee73aeb00402bc8a5d0708af299e9f4a33f5132805449099295085e3ca3b0d018328bad9ff44cf2e6f4cd364f1d558d3fb9b394243a25b2739207edcb0ed + languageName: node + linkType: hard + "vscode-oniguruma@npm:^1.7.0": version: 1.7.0 resolution: "vscode-oniguruma@npm:1.7.0" @@ -17204,6 +19430,13 @@ __metadata: languageName: node linkType: hard +"web-namespaces@npm:^2.0.0": + version: 2.0.1 + resolution: "web-namespaces@npm:2.0.1" + checksum: b6d9f02f1a43d0ef0848a812d89c83801d5bbad57d8bb61f02eb6d7eb794c3736f6cc2e1191664bb26136594c8218ac609f4069722c6f56d9fc2d808fa9271c6 + languageName: node + linkType: hard + "web-streams-polyfill@npm:^3.0.3": version: 3.2.1 resolution: "web-streams-polyfill@npm:3.2.1" @@ -17225,30 +19458,26 @@ __metadata: languageName: node linkType: hard -"webpack-bundle-analyzer@npm:^4.5.0": - version: 4.9.1 - resolution: "webpack-bundle-analyzer@npm:4.9.1" +"webpack-bundle-analyzer@npm:^4.5.0, webpack-bundle-analyzer@npm:^4.9.0": + version: 4.10.1 + resolution: "webpack-bundle-analyzer@npm:4.10.1" dependencies: "@discoveryjs/json-ext": 0.5.7 acorn: ^8.0.4 acorn-walk: ^8.0.0 commander: ^7.2.0 + debounce: ^1.2.1 escape-string-regexp: ^4.0.0 gzip-size: ^6.0.0 + html-escaper: ^2.0.2 is-plain-object: ^5.0.0 - lodash.debounce: ^4.0.8 - lodash.escape: ^4.0.1 - lodash.flatten: ^4.4.0 - lodash.invokemap: ^4.6.0 - lodash.pullall: ^4.2.0 - lodash.uniqby: ^4.7.0 opener: ^1.5.2 picocolors: ^1.0.0 sirv: ^2.0.3 ws: ^7.3.1 bin: webpack-bundle-analyzer: lib/bin/analyzer.js - checksum: 7e891c28d5a903242893e55ecc714fa01d7ad6bedade143235c07091b235915349812fa048968462781d59187507962f38b6c61ed7d25fb836ba0ac0ee919a39 + checksum: 77f48f10a493b1cc95674526472978a2de32412ddbf556bd3903738f14890611426f19477352993efe5a9fd6ca16711eb912d986f2221b17ba6eeca1b6f71fb6 languageName: node linkType: hard @@ -17267,7 +19496,7 @@ __metadata: languageName: node linkType: hard -"webpack-dev-server@npm:^4.9.3": +"webpack-dev-server@npm:^4.15.1, webpack-dev-server@npm:^4.9.3": version: 4.15.1 resolution: "webpack-dev-server@npm:4.15.1" dependencies: @@ -17314,13 +19543,14 @@ __metadata: languageName: node linkType: hard -"webpack-merge@npm:^5.8.0": - version: 5.9.0 - resolution: "webpack-merge@npm:5.9.0" +"webpack-merge@npm:^5.8.0, webpack-merge@npm:^5.9.0": + version: 5.10.0 + resolution: "webpack-merge@npm:5.10.0" dependencies: clone-deep: ^4.0.1 + flat: ^5.0.2 wildcard: ^2.0.0 - checksum: 64fe2c23aacc5f19684452a0e84ec02c46b990423aee6fcc5c18d7d471155bd14e9a6adb02bd3656eb3e0ac2532c8e97d69412ad14c97eeafe32fa6d10050872 + checksum: 1fe8bf5309add7298e1ac72fb3f2090e1dfa80c48c7e79fa48aa60b5961332c7d0d61efa8851acb805e6b91a4584537a347bc106e05e9aec87fa4f7088c62f2f languageName: node linkType: hard @@ -17331,7 +19561,7 @@ __metadata: languageName: node linkType: hard -"webpack@npm:^5.73.0": +"webpack@npm:^5.73.0, webpack@npm:^5.88.1": version: 5.89.0 resolution: "webpack@npm:5.89.0" dependencies: @@ -17400,13 +19630,6 @@ __metadata: languageName: node linkType: hard -"well-known-symbols@npm:^2.0.0": - version: 2.0.0 - resolution: "well-known-symbols@npm:2.0.0" - checksum: 4f54bbc3012371cb4d228f436891b8e7536d34ac61a57541890257e96788608e096231e0121ac24d08ef2f908b3eb2dc0adba35023eaeb2a7df655da91415402 - languageName: node - linkType: hard - "whatwg-url@npm:^11.0.0": version: 11.0.0 resolution: "whatwg-url@npm:11.0.0" @@ -17449,12 +19672,14 @@ __metadata: languageName: node linkType: hard -"wide-align@npm:^1.1.5": - version: 1.1.5 - resolution: "wide-align@npm:1.1.5" +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" dependencies: - string-width: ^1.0.2 || 2 || 3 || 4 - checksum: d5fc37cd561f9daee3c80e03b92ed3e84d80dde3365a8767263d03dacfc8fa06b065ffe1df00d8c2a09f731482fcacae745abfbb478d4af36d0a891fad4834d3 + isexe: ^3.1.1 + bin: + node-which: bin/which.js + checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 languageName: node linkType: hard @@ -17547,7 +19772,7 @@ __metadata: languageName: node linkType: hard -"write-file-atomic@npm:^3.0.0": +"write-file-atomic@npm:^3.0.0, write-file-atomic@npm:^3.0.3": version: 3.0.3 resolution: "write-file-atomic@npm:3.0.3" dependencies: @@ -17559,16 +19784,6 @@ __metadata: languageName: node linkType: hard -"write-file-atomic@npm:^5.0.1": - version: 5.0.1 - resolution: "write-file-atomic@npm:5.0.1" - dependencies: - imurmurhash: ^0.1.4 - signal-exit: ^4.0.1 - checksum: 8dbb0e2512c2f72ccc20ccedab9986c7d02d04039ed6e8780c987dc4940b793339c50172a1008eed7747001bfacc0ca47562668a069a7506c46c77d7ba3926a9 - languageName: node - linkType: hard - "ws@npm:7.4.6": version: 7.4.6 resolution: "ws@npm:7.4.6" @@ -17630,8 +19845,8 @@ __metadata: linkType: hard "ws@npm:^8.13.0": - version: 8.14.2 - resolution: "ws@npm:8.14.2" + version: 8.15.0 + resolution: "ws@npm:8.15.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -17640,7 +19855,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 3ca0dad26e8cc6515ff392b622a1467430814c463b3368b0258e33696b1d4bed7510bc7030f7b72838b9fdeb8dbd8839cbf808367d6aae2e1d668ce741d4308b + checksum: ca15c590aa49bc0197223b8ab7d15e7362ae6c4011d91ed0e5cd5867cdd5497fd71470ea36314833b4b078929fe64dc4ba7748b1e58e50a0f8e41f147db2b464 languageName: node linkType: hard @@ -17651,6 +19866,13 @@ __metadata: languageName: node linkType: hard +"xdg-basedir@npm:^5.0.1, xdg-basedir@npm:^5.1.0": + version: 5.1.0 + resolution: "xdg-basedir@npm:5.1.0" + checksum: b60e8a2c663ccb1dac77c2d913f3b96de48dafbfa083657171d3d50e10820b8a04bb4edfe9f00808c8c20e5f5355e1927bea9029f03136e29265cb98291e1fea + languageName: node + linkType: hard + "xml-js@npm:^1.6.11": version: 1.6.11 resolution: "xml-js@npm:1.6.11" @@ -17697,17 +19919,10 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.1.1": - version: 2.3.2 - resolution: "yaml@npm:2.3.2" - checksum: acd80cc24df12c808c6dec8a0176d404ef9e6f08ad8786f746ecc9d8974968c53c6e8a67fdfabcc5f99f3dc59b6bb0994b95646ff03d18e9b1dcd59eccc02146 - languageName: node - linkType: hard - -"yaml@npm:^2.2.2": - version: 2.3.3 - resolution: "yaml@npm:2.3.3" - checksum: cdfd132e7e0259f948929efe8835923df05c013c273c02bb7a2de9b46ac3af53c2778a35b32c7c0f877cc355dc9340ed564018c0242bfbb1278c2a3e53a0e99e +"yaml@npm:^2.1.1, yaml@npm:^2.2.2": + version: 2.3.4 + resolution: "yaml@npm:2.3.4" + checksum: e6d1dae1c6383bcc8ba11796eef3b8c02d5082911c6723efeeb5ba50fc8e881df18d645e64de68e421b577296000bea9c75d6d9097c2f6699da3ae0406c030d8 languageName: node linkType: hard @@ -17774,7 +19989,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^17.7.1, yargs@npm:^17.7.2": +"yargs@npm:^17.7.1": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: @@ -17834,6 +20049,13 @@ __metadata: languageName: node linkType: hard +"zwitch@npm:^2.0.0": + version: 2.0.4 + resolution: "zwitch@npm:2.0.4" + checksum: f22ec5fc2d5f02c423c93d35cdfa83573a3a3bd98c66b927c368ea4d0e7252a500df2a90a6b45522be536a96a73404393c958e945fdba95e6832c200791702b6 + languageName: node + linkType: hard + "zx@npm:7.1.1": version: 7.1.1 resolution: "zx@npm:7.1.1"