diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 784988b0ce8..e81ede7199d 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,37 +1,23 @@ # Description - - - ## Problem\* - - Resolves ## Summary\* - - - -## Documentation - -- [ ] This PR requires documentation updates when merged. - - - [ ] I will submit a noir-lang/docs PR. - - +## Additional Context - - [ ] I will request for and support Dev Rel's help in documenting this PR. - - -## Additional Context +## Documentation\* - +Check one: +- [ ] No documentation needed. +- [ ] Documentation included in this PR. +- [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist\* diff --git a/.github/workflows/auto-pr-rebuild-script.yml b/.github/workflows/auto-pr-rebuild-script.yml index 5e46e46ed4c..4937de98e04 100644 --- a/.github/workflows/auto-pr-rebuild-script.yml +++ b/.github/workflows/auto-pr-rebuild-script.yml @@ -1,13 +1,45 @@ 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] @@ -17,7 +49,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.66.0 + uses: dtolnay/rust-toolchain@1.71.1 - uses: Swatinem/rust-cache@v2 with: @@ -42,12 +74,13 @@ jobs: 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@v2 + uses: actions/checkout@v4 - name: Download nargo binary uses: actions/download-artifact@v3 @@ -71,8 +104,16 @@ jobs: 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" diff --git a/.github/workflows/build-aztec-feature-flag.yml b/.github/workflows/build-aztec-feature-flag.yml new file mode 100644 index 00000000000..888a88a7f88 --- /dev/null +++ b/.github/workflows/build-aztec-feature-flag.yml @@ -0,0 +1,45 @@ +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/build-docs.yml b/.github/workflows/build-docs.yml deleted file mode 100644 index 23ae0e409e9..00000000000 --- a/.github/workflows/build-docs.yml +++ /dev/null @@ -1,142 +0,0 @@ -name: Build docs - -on: - pull_request: - paths: - - 'docs/**' - types: - - opened - - synchronize - - labeled - -jobs: - add_label: - runs-on: ubuntu-latest - outputs: - has_label: ${{ steps.check-labels.outputs.result }} - steps: - - name: Check if label is present - id: check-labels - uses: actions/github-script@v3 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const labels = context.payload.pull_request.labels.map(label => label.name); - if (labels.includes('documentation')) { - return true; - } - - // Fetch the list of files changed in the PR - const { data: files } = await github.pulls.listFiles({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.issue.number - }); - - // Check if any file is within the 'docs' folder - const docsChanged = files.some(file => file.filename.startsWith('docs/')); - return docsChanged; - - - name: Add label if not present - if: steps.check-labels.outputs.result == 'true' - uses: actions/github-script@v3 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const labels = context.payload.pull_request.labels.map(label => label.name); - if (!labels.includes('documentation')) { - github.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - labels: ['documentation'] - }) - } - - deploy_docs: - runs-on: ubuntu-latest - permissions: - pull-requests: write - needs: add_label - if: needs.add_label.outputs.has_label == 'true' - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Netlify deploy - run: | - BRANCH_NAME=$(echo "${{ github.head_ref || github.ref }}" | sed -e "s#refs/[^/]*/##") - curl -X POST -d {} "https://api.netlify.com/build_hooks/${{ secrets.NETLIFY_BUILD_HOOK }}?trigger_branch=$BRANCH_NAME" - - name: Get deploy preview - id: get_deploy_preview - run: | - BRANCH_NAME=$(echo "${{ github.head_ref || github.ref }}" | sed -e "s#refs/[^/]*/##") - curl -X GET "https://api.netlify.com/api/v1/sites/${{ secrets.NETLIFY_SITE_ID }}/deploys?branch=$BRANCH_NAME" > deploy.json - echo "::set-output name=deploy_url::$(cat deploy.json | jq -r '.[0].deploy_ssl_url')" - - - name: Add PR Comment - uses: mshick/add-pr-comment@v2 - with: - message: | - Hey @${{ github.event.pull_request.user.login }}! 🙌 - - I'm the deployment bot for Noir Docs, and I've got some updates for you: - - ## Deployment Status - Your latest changes are being deployed for preview! 🚀 - - Click the badge to see logs 🧐 - - [![Netlify Status](https://api.netlify.com/api/v1/badges/${{ secrets.NETLIFY_SITE_ID }}/deploy-status?branch=${{ github.head_ref || github.ref }})](https://app.netlify.com/sites/noir-docs-v2/deploys) - - If you have any questions about this process, refer to our contribution guide or feel free to ask around. - - - - name: Check on deploy status - uses: ./.github/actions/docs/build-status - id: check_deploy_status - with: - branch-name: ${{ github.head_ref || github.ref }} - site-id: ${{ secrets.NETLIFY_SITE_ID }} - continue-on-error: true - - - - name: Debugging - print deploy_status - run: echo "${{ steps.check_deploy_status.outputs.deploy_status }}" - - - - name: Change PR Comment for Successful Deployment - if: steps.check_deploy_status.outputs.deploy_status == 'success' - uses: mshick/add-pr-comment@v2 - with: - message-success: | - ![It's Alive!](https://i.imgflip.com/82hw5n.jpg) - - I'm a bot, beep boop 🤖 - - ## Deployment Status: Success! - [![Netlify Status](https://api.netlify.com/api/v1/badges/${{ secrets.NETLIFY_SITE_ID }}/deploy-status?branch=${{ github.head_ref || github.ref }})](https://app.netlify.com/sites/noir-docs-v2/deploys) - - ## Preview - - 🌐 [View Deployment Preview](${{ steps.get_deploy_preview.outputs.deploy_url }}) - - - - - name: Change PR Comment for Failed Deployment - if: steps.check_deploy_status.outputs.deploy_status == 'failure' - uses: mshick/add-pr-comment@v2 - with: - message: | - ![docs CI troll](https://i.imgflip.com/82ht8f.jpg) - - I'm a bot, beep boop 🤖 - - ## Deployment Status: Failed ❌ - Deployment didn't succeed. Please check logs below and resolve the issue 🧐 - - [![Netlify Status](https://api.netlify.com/api/v1/badges/${{ secrets.NETLIFY_SITE_ID }}/deploy-status?branch=${{ github.head_ref || github.ref }})](https://app.netlify.com/sites/noir-docs-v2/deploys) - - - name: Fail the workflow if deployment failed - if: steps.check_deploy_status.outputs.deploy_status == 'failure' - run: exit 1 diff --git a/.github/workflows/docs-new-version.yml b/.github/workflows/docs-new-version.yml new file mode 100644 index 00000000000..9b109e170bb --- /dev/null +++ b/.github/workflows/docs-new-version.yml @@ -0,0 +1,112 @@ +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 new file mode 100644 index 00000000000..02044c82224 --- /dev/null +++ b/.github/workflows/docs-pr.yml @@ -0,0 +1,113 @@ +name: Deploy preview for PR + +on: + pull_request: + +jobs: + add_label: + runs-on: ubuntu-latest + outputs: + has_label: ${{ steps.check-labels.outputs.result }} + steps: + - name: Check if label is present + id: check-labels + uses: actions/github-script@v3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const labels = context.payload.pull_request.labels.map(label => label.name); + if (labels.includes('documentation')) { + return true; + } + + // Fetch the list of files changed in the PR + const { data: files } = await github.pulls.listFiles({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number + }); + + // Check if any file is within the 'docs' folder + const docsChanged = files.some(file => file.filename.startsWith('docs/')); + return docsChanged; + + - name: Add label if not present + if: steps.check-labels.outputs.result == 'true' + uses: actions/github-script@v3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const labels = context.payload.pull_request.labels.map(label => label.name); + if (!labels.includes('documentation')) { + github.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + labels: ['documentation'] + }) + } + + build_and_deploy_preview: + runs-on: ubuntu-latest + permissions: + pull-requests: write + needs: add_label + if: needs.add_label.outputs.has_label == 'true' + 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' + github-token: ${{ secrets.GITHUB_TOKEN }} + enable-github-deployment: false + deploy-message: "Deploy from GitHub Actions for PR ${{ github.event.number }}" + env: + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + timeout-minutes: 1 diff --git a/.github/workflows/docs-release.yml b/.github/workflows/docs-release.yml new file mode 100644 index 00000000000..4cd9d9998cb --- /dev/null +++ b/.github/workflows/docs-release.yml @@ -0,0 +1,72 @@ +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/formatting.yml b/.github/workflows/formatting.yml index 3fa070106cd..97736e2415e 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.66.0 + uses: dtolnay/rust-toolchain@1.71.1 with: targets: ${{ matrix.target }} components: clippy, rustfmt diff --git a/.github/workflows/gates_report.yml b/.github/workflows/gates_report.yml index e2d6bdd56b7..41a68c65852 100644 --- a/.github/workflows/gates_report.yml +++ b/.github/workflows/gates_report.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.66.0 + uses: dtolnay/rust-toolchain@1.71.1 - uses: Swatinem/rust-cache@v2 with: diff --git a/.github/workflows/publish-acvm.yml b/.github/workflows/publish-acvm.yml index 3f4641a690c..ded669f13d0 100644 --- a/.github/workflows/publish-acvm.yml +++ b/.github/workflows/publish-acvm.yml @@ -18,9 +18,7 @@ jobs: ref: ${{ inputs.acvm-ref }} - name: Setup toolchain - uses: dtolnay/rust-toolchain@master - with: - toolchain: 1.66.0 + uses: dtolnay/rust-toolchain@1.71.1 # These steps are in a specific order so crate dependencies are updated first - name: Publish acir_field diff --git a/.github/workflows/publish-es-packages.yml b/.github/workflows/publish-es-packages.yml index 14630434453..2e88ee2b77f 100644 --- a/.github/workflows/publish-es-packages.yml +++ b/.github/workflows/publish-es-packages.yml @@ -27,7 +27,7 @@ jobs: uses: ./.github/actions/nix with: github-token: ${{ secrets.GITHUB_TOKEN }} - nix-cache-name: ${{ vars.NIX_CACHE_NAME }} + nix-cache-name: "noir" cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - name: Enable aztec features @@ -58,7 +58,7 @@ jobs: uses: ./.github/actions/nix with: github-token: ${{ secrets.GITHUB_TOKEN }} - nix-cache-name: ${{ vars.NIX_CACHE_NAME }} + nix-cache-name: "noir" cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - name: Build wasm package @@ -84,7 +84,7 @@ jobs: uses: ./.github/actions/nix with: github-token: ${{ secrets.GITHUB_TOKEN }} - nix-cache-name: ${{ vars.NIX_CACHE_NAME }} + nix-cache-name: "noir" cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - name: Build wasm package diff --git a/.github/workflows/publish-nargo.yml b/.github/workflows/publish-nargo.yml index fa642de8a4f..59d4fe4cc48 100644 --- a/.github/workflows/publish-nargo.yml +++ b/.github/workflows/publish-nargo.yml @@ -45,7 +45,7 @@ jobs: echo "MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx$(sw_vers -productVersion) --show-sdk-platform-version)" >> $GITHUB_ENV - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.66.0 + uses: dtolnay/rust-toolchain@1.71.1 with: targets: ${{ matrix.target }} @@ -128,7 +128,7 @@ jobs: ref: ${{ inputs.tag || env.GITHUB_REF }} - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.66.0 + uses: dtolnay/rust-toolchain@1.71.1 with: targets: ${{ matrix.target }} @@ -177,6 +177,7 @@ jobs: repo_token: ${{ secrets.GITHUB_TOKEN }} file: ./nargo-${{ matrix.target }}.tar.gz asset_name: nargo-${{ matrix.target }}.tar.gz + prerelease: true overwrite: true tag: ${{ inputs.tag || 'nightly' }} # This will fail if `inputs.tag` is not a tag (e.g. testing a branch) @@ -198,4 +199,4 @@ jobs: overwrite: true tag: ${{ format('{0}-{1}', 'nightly', steps.date.outputs.date) }} - \ No newline at end of file + diff --git a/.github/workflows/recrawler.yml b/.github/workflows/recrawler.yml new file mode 100644 index 00000000000..ee832e273a1 --- /dev/null +++ b/.github/workflows/recrawler.yml @@ -0,0 +1,22 @@ +name: Algolia Recrawl +on: + push: + branches: [ master ] + workflow_dispatch: + +jobs: + algolia_recrawl: + name: Algolia Recrawl + runs-on: ubuntu-latest + steps: + - name: Algolia crawler creation and crawl + uses: algolia/algoliasearch-crawler-github-actions@v1.1.0 + id: algolia_crawler + with: + crawler-user-id: ${{ secrets.CRAWLER_USER_ID }} + crawler-api-key: ${{ secrets.CRAWLER_API_KEY }} + algolia-app-id: ${{ secrets.ALGOLIA_APP_ID }} + algolia-api-key: ${{ secrets.ALGOLIA_API_KEY }} + site-url: 'https://noir-lang.org/' + crawler-name: noir-lang + override-config: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2786bc32970..95da6792f04 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -77,4 +77,20 @@ jobs: workflow: publish-es-packages.yml ref: master token: ${{ secrets.NOIR_REPO_TOKEN }} - inputs: '{ "noir-ref": "${{ needs.release-please.outputs.tag-name }}", "npm-tag": "latest" }' \ No newline at end of file + 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 + uses: benc-uk/workflow-dispatch@v1 + with: + workflow: docs-new-version.yml + repo: noir-lang/noir + ref: master + token: ${{ secrets.GITHUB_TOKEN }} + inputs: '{ "tag": "${{ needs.release-please.outputs.tag-name }}"}' diff --git a/.github/workflows/test-abi_wasm.yml b/.github/workflows/test-abi_wasm.yml index 7fecb66fd7f..52223d874bf 100644 --- a/.github/workflows/test-abi_wasm.yml +++ b/.github/workflows/test-abi_wasm.yml @@ -15,23 +15,17 @@ concurrency: jobs: build: runs-on: ubuntu-latest - env: - CACHED_PATH: /tmp/nix-cache steps: - name: Checkout sources uses: actions/checkout@v3 - name: Setup Nix - uses: cachix/install-nix-action@v22 + uses: ./.github/actions/nix with: - nix_path: nixpkgs=channel:nixos-23.05 - github_access_token: ${{ secrets.GITHUB_TOKEN }} - - - uses: cachix/cachix-action@v12 - with: - name: barretenberg - authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" + github-token: ${{ secrets.GITHUB_TOKEN }} + nix-cache-name: "noir" + cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - name: Build noirc_abi_wasm run: | diff --git a/.github/workflows/test-acvm-js.yml b/.github/workflows/test-acvm-js.yml index c69f4995198..14ce5d916c0 100644 --- a/.github/workflows/test-acvm-js.yml +++ b/.github/workflows/test-acvm-js.yml @@ -19,15 +19,12 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v20 + - name: Setup Nix + uses: ./.github/actions/nix with: - nix_path: nixpkgs=channel:nixos-22.11 - github_access_token: ${{ secrets.GITHUB_TOKEN }} - - - uses: cachix/cachix-action@v12 - with: - name: barretenberg - authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" + github-token: ${{ secrets.GITHUB_TOKEN }} + nix-cache-name: "noir" + cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - name: Build acvm-js run: | diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index f3bb953f676..ad28d9c8e86 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.66.0 + uses: dtolnay/rust-toolchain@1.71.1 - uses: Swatinem/rust-cache@v2 with: @@ -43,41 +43,50 @@ jobs: path: ./dist/* retention-days: 3 - build-wasm: + build-acvm-js: runs-on: ubuntu-latest - env: - CACHED_PATH: /tmp/nix-cache - steps: - name: Checkout sources uses: actions/checkout@v4 - name: Setup Nix - uses: cachix/install-nix-action@v22 + uses: ./.github/actions/nix with: - nix_path: nixpkgs=channel:nixos-23.05 - github_access_token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.GITHUB_TOKEN }} + nix-cache-name: "noir" + cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} + + - name: Build acvm-js + run: | + nix build -L .#acvm_js - - uses: cachix/cachix-action@v12 + - name: Dereference symlink + run: echo "UPLOAD_PATH=$(readlink -f result/acvm_js)" >> $GITHUB_ENV + + - name: Upload artifact + uses: actions/upload-artifact@v3 with: - name: barretenberg - authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" + name: acvm-js + path: ${{ env.UPLOAD_PATH }} + retention-days: 3 - - name: Build wasm package - run: | - nix build -L .#noir_wasm + build-wasm: + runs-on: ubuntu-latest - - name: Export cache from nix store - if: ${{ steps.cache.outputs.cache-hit != 'true' && github.event_name != 'merge_group' }} - run: | - nix copy --to "file://${{ env.CACHED_PATH }}?compression=zstd¶llel-compression=true" .#noir-wasm-cargo-artifacts + steps: + - name: Checkout sources + uses: actions/checkout@v4 - - uses: actions/cache/save@v3 - # Don't create cache entries for the merge queue. - if: ${{ steps.cache.outputs.cache-hit != 'true' && github.event_name != 'merge_group' }} + - name: Setup Nix + uses: ./.github/actions/nix with: - path: ${{ env.CACHED_PATH }} - key: ${{ steps.cache.outputs.cache-primary-key }} + 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 @@ -91,40 +100,17 @@ jobs: build-noirc: runs-on: ubuntu-latest - env: - CACHED_PATH: /tmp/nix-cache steps: - name: Checkout sources uses: actions/checkout@v3 - name: Setup Nix - uses: cachix/install-nix-action@v22 - with: - nix_path: nixpkgs=channel:nixos-23.05 - github_access_token: ${{ secrets.GITHUB_TOKEN }} - - - uses: cachix/cachix-action@v12 - with: - name: barretenberg - authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" - - - name: Restore nix store cache - uses: actions/cache/restore@v3 - id: cache + uses: ./.github/actions/nix with: - path: ${{ env.CACHED_PATH }} - key: ${{ runner.os }}-flake-abi-wasm-${{ hashFiles('*.lock') }} - - # Based on https://github.com/marigold-dev/deku/blob/b5016f0cf4bf6ac48db9111b70dd7fb49b969dfd/.github/workflows/build.yml#L26 - - name: Copy cache into nix store - if: steps.cache.outputs.cache-hit == 'true' - # We don't check the signature because we're the one that created the cache - run: | - for narinfo in ${{ env.CACHED_PATH }}/*.narinfo; do - path=$(head -n 1 "$narinfo" | awk '{print $2}') - nix copy --no-check-sigs --from "file://${{ env.CACHED_PATH }}" "$path" - done + github-token: ${{ secrets.GITHUB_TOKEN }} + nix-cache-name: "noir" + cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - name: Build noirc_abi_wasm run: | @@ -132,18 +118,6 @@ jobs: cp -r ./result/noirc_abi_wasm/nodejs ./tooling/noirc_abi_wasm cp -r ./result/noirc_abi_wasm/web ./tooling/noirc_abi_wasm - - name: Export cache from nix store - if: ${{ steps.cache.outputs.cache-hit != 'true' && github.event_name != 'merge_group' }} - run: | - nix copy --to "file://${{ env.CACHED_PATH }}?compression=zstd¶llel-compression=true" .#noirc-abi-wasm-cargo-artifacts - - - uses: actions/cache/save@v3 - # Don't create cache entries for the merge queue. - if: ${{ steps.cache.outputs.cache-hit != 'true' && github.event_name != 'merge_group' }} - with: - path: ${{ env.CACHED_PATH }} - key: ${{ steps.cache.outputs.cache-primary-key }} - - name: Dereference symlink run: echo "UPLOAD_PATH=$(readlink -f ./result/noirc_abi_wasm)" >> $GITHUB_ENV @@ -156,7 +130,7 @@ jobs: test-solidity-verifier: runs-on: ubuntu-latest - needs: [build-wasm, build-nargo, build-noirc] + needs: [build-acvm-js, build-wasm, build-nargo, build-noirc] env: CACHED_PATH: /tmp/nix-cache @@ -170,13 +144,19 @@ jobs: name: nargo path: ./nargo - - name: Download wasm package artifact + - 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 package artifact + - name: Download noirc_abi package artifact uses: actions/download-artifact@v3 with: name: noirc_abi_wasm @@ -196,22 +176,9 @@ jobs: - name: Install Playwright uses: ./.github/actions/install-playwright - - 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: Setup `integration-tests` run: | yarn workspace @noir-lang/source-resolver build - yarn workspace @noir-lang/acvm_js build yarn workspace @noir-lang/types build yarn workspace @noir-lang/backend_barretenberg build yarn workspace @noir-lang/noir_js build diff --git a/.github/workflows/test-noir-js.yml b/.github/workflows/test-noir-js.yml index 8f1862bdfdc..e74f2ee6015 100644 --- a/.github/workflows/test-noir-js.yml +++ b/.github/workflows/test-noir-js.yml @@ -21,7 +21,7 @@ jobs: uses: ./.github/actions/setup - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.66.0 + uses: dtolnay/rust-toolchain@1.71.1 with: targets: wasm32-unknown-unknown diff --git a/.github/workflows/test-noir_wasm.yml b/.github/workflows/test-noir_wasm.yml index eea4074e00a..2175e20acd7 100644 --- a/.github/workflows/test-noir_wasm.yml +++ b/.github/workflows/test-noir_wasm.yml @@ -23,7 +23,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.66.0 + uses: dtolnay/rust-toolchain@1.71.1 - uses: Swatinem/rust-cache@v2 with: @@ -49,23 +49,17 @@ jobs: build-wasm: runs-on: ubuntu-latest - env: - CACHED_PATH: /tmp/nix-cache steps: - name: Checkout sources uses: actions/checkout@v4 - name: Setup Nix - uses: cachix/install-nix-action@v22 + uses: ./.github/actions/nix with: - nix_path: nixpkgs=channel:nixos-23.05 - github_access_token: ${{ secrets.GITHUB_TOKEN }} - - - uses: cachix/cachix-action@v12 - with: - name: barretenberg - authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" + github-token: ${{ secrets.GITHUB_TOKEN }} + nix-cache-name: "noir" + cachix-auth-token: ${{ secrets.CACHIXAUTHTOKEN }} - name: Build wasm package run: | diff --git a/.github/workflows/test-rust-workspace.yml b/.github/workflows/test-rust-workspace.yml index e5a94aaac4b..eccd7585fcf 100644 --- a/.github/workflows/test-rust-workspace.yml +++ b/.github/workflows/test-rust-workspace.yml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v4 - name: Setup toolchain - uses: dtolnay/rust-toolchain@1.66.0 + uses: dtolnay/rust-toolchain@1.71.1 with: targets: ${{ matrix.target }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3a52db26d13..ea8ab2395df 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,4 +1,4 @@ { - ".": "0.18.0", - "acvm-repo": "0.30.0" + ".": "0.19.2", + "acvm-repo": "0.33.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 68cd1decb44..cacf629d818 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,84 @@ # Changelog +## [0.19.2](https://github.com/noir-lang/noir/compare/v0.19.1...v0.19.2) (2023-11-07) + + +### Features + +* Add profile info print out ([#3425](https://github.com/noir-lang/noir/issues/3425)) ([a8b5fa8](https://github.com/noir-lang/noir/commit/a8b5fa8e30dc27e64666381b7451569f350967d1)) + +## [0.19.1](https://github.com/noir-lang/noir/compare/v0.19.0...v0.19.1) (2023-11-07) + + +### Features + +* **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)) +* 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)) +* 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)) + + +### Bug Fixes + +* 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)) +* Overflow checks for constant folding ([#3420](https://github.com/noir-lang/noir/issues/3420)) ([b7a6383](https://github.com/noir-lang/noir/commit/b7a6383cf9dc3bc4a71b9644352340c1e9339c81)) + +## [0.19.0](https://github.com/noir-lang/noir/compare/v0.18.0...v0.19.0) (2023-11-02) + + +### ⚠ 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)) + +### 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)) +* Add `noir_codegen` package ([#3392](https://github.com/noir-lang/noir/issues/3392)) ([6c4cd4d](https://github.com/noir-lang/noir/commit/6c4cd4d37e4af38dccf899bcbd3950d1e236b35d)) +* 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 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 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)) +* 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 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)) +* 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)) +* 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)) +* 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)) +* Handle warnings in evaluator ([#3205](https://github.com/noir-lang/noir/issues/3205)) ([5cfd156](https://github.com/noir-lang/noir/commit/5cfd156ca2035038a226bdd81a51636d3de3c34e)) +* Implement where clauses on impls ([#3324](https://github.com/noir-lang/noir/issues/3324)) ([4c3d1de](https://github.com/noir-lang/noir/commit/4c3d1dea27726133335538443df3dbbd2c8f2d58)) +* 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)) +* **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)) +* 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)) +* 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)) +* Return Pedersen structure in stdlib ([#3190](https://github.com/noir-lang/noir/issues/3190)) ([be30d59](https://github.com/noir-lang/noir/commit/be30d59e61a9dff6ab94ffb97365c1282c331643)) + + +### Bug Fixes + +* `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)) +* **aztec_nr:** Serialise arrays of structs ([#3401](https://github.com/noir-lang/noir/issues/3401)) ([e979a58](https://github.com/noir-lang/noir/commit/e979a587e755d4b715ebacba715d778938026ac0)) +* Fixing versioning workflow ([#3296](https://github.com/noir-lang/noir/issues/3296)) ([3d5e43a](https://github.com/noir-lang/noir/commit/3d5e43a4b8cd9d2bb67d44a2eff93374c3603e42)) +* Move mimc to hash submodule ([#3361](https://github.com/noir-lang/noir/issues/3361)) ([3ec29f1](https://github.com/noir-lang/noir/commit/3ec29f17464703716978daacfa9f00c4f5013551)) +* Remove sha2_block test ([#3360](https://github.com/noir-lang/noir/issues/3360)) ([a48c03b](https://github.com/noir-lang/noir/commit/a48c03bec786d1fb85eef46eeddeccf29e81fe76)) +* Use pedersen_hash for merkle tree ([#3357](https://github.com/noir-lang/noir/issues/3357)) ([6b74d31](https://github.com/noir-lang/noir/commit/6b74d316fec3b379dd7b51064f1acb1a0e6a15cc)) + + +### Miscellaneous Chores + +* 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)) + ## [0.18.0](https://github.com/noir-lang/noir/compare/v0.17.0...v0.18.0) (2023-10-25) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bc2acd40829..9cbbeeb677f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -187,7 +187,7 @@ In the docs folder, you'll find the current, unreleased version, which we call ` While the versioning is intended to be managed by the core maintainers, we feel it's important for external contributors to understand why and how is it maintained. To bump to a new version, run the following command, replacing with the intended version: ```bash -npm run docusaurus docs:version +yarn docusaurus docs:version ``` This should create a new version by copying the docs folder and the sidebars.js file to the relevant folders, as well as adding this version to versions.json. diff --git a/Cargo.lock b/Cargo.lock index 648b79e2d2b..52c735a0b5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,10 @@ version = 3 [[package]] name = "acir" -version = "0.30.0" +version = "0.33.0" dependencies = [ "acir_field", + "base64", "bincode", "brillig", "flate2", @@ -22,7 +23,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.30.0" +version = "0.33.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -36,7 +37,7 @@ dependencies = [ [[package]] name = "acvm" -version = "0.30.0" +version = "0.33.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -53,7 +54,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.30.0" +version = "0.33.0" dependencies = [ "acir", "blake2", @@ -67,7 +68,7 @@ dependencies = [ [[package]] name = "acvm_js" -version = "0.30.0" +version = "0.33.0" dependencies = [ "acvm", "barretenberg_blackbox_solver", @@ -88,7 +89,7 @@ dependencies = [ [[package]] name = "acvm_stdlib" -version = "0.30.0" +version = "0.33.0" dependencies = [ "acir", ] @@ -110,9 +111,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ "getrandom", "once_cell", @@ -163,16 +164,15 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.3.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] @@ -202,9 +202,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -218,7 +218,7 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arena" -version = "0.18.0" +version = "0.19.2" dependencies = [ "generational-arena", ] @@ -396,14 +396,14 @@ dependencies = [ [[package]] name = "async-lsp" -version = "0.0.5" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72bd600f2652d2cccb0a33ab4f92d163ab3930844c8b0ad3713a5ae3285eeb4e" +checksum = "138985dd8aefbefeaa66b01b7f5b2b6b4c333fcef1cc5f32c63a2aabe37d6de3" dependencies = [ "futures", - "lsp-types 0.94.0", + "lsp-types 0.94.1", "pin-project-lite", - "rustix 0.38.4", + "rustix", "serde", "serde_json", "thiserror", @@ -456,7 +456,7 @@ dependencies = [ [[package]] name = "barretenberg_blackbox_solver" -version = "0.30.0" +version = "0.33.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -593,7 +593,7 @@ dependencies = [ [[package]] name = "brillig" -version = "0.30.0" +version = "0.33.0" dependencies = [ "acir_field", "serde", @@ -601,7 +601,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.30.0" +version = "0.33.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -802,20 +802,19 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.19" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.3.19" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", @@ -825,9 +824,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.12" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -837,9 +836,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "clipboard-win" @@ -1166,6 +1165,16 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.16" @@ -1498,25 +1507,14 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys 0.48.0", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "error-code" version = "2.3.1" @@ -1545,12 +1543,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fd-lock" @@ -1559,7 +1554,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" dependencies = [ "cfg-if", - "rustix 0.38.4", + "rustix", "windows-sys 0.48.0", ] @@ -1627,7 +1622,7 @@ dependencies = [ [[package]] name = "fm" -version = "0.18.0" +version = "0.19.2" dependencies = [ "codespan-reporting", "iter-extended", @@ -1888,7 +1883,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.7", ] [[package]] @@ -1897,7 +1892,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash 0.7.6", + "ahash 0.7.7", ] [[package]] @@ -2031,16 +2026,16 @@ checksum = "71a816c97c42258aa5834d07590b718b4c9a598944cd39a52dc25b351185d678" [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -2094,6 +2089,7 @@ dependencies = [ "bitmaps", "rand_core", "rand_xoshiro", + "serde", "sized-chunks", "typenum", "version_check", @@ -2169,26 +2165,6 @@ dependencies = [ "str_stack", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ipnet" version = "2.8.0" @@ -2202,13 +2178,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", - "rustix 0.38.4", + "rustix", "windows-sys 0.48.0", ] [[package]] name = "iter-extended" -version = "0.18.0" +version = "0.19.2" [[package]] name = "itertools" @@ -2279,12 +2255,6 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - [[package]] name = "linux-raw-sys" version = "0.4.3" @@ -2331,9 +2301,9 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.94.0" +version = "0.94.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b63735a13a1f9cd4f4835223d828ed9c2e35c8c5e61837774399f558b6a1237" +checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1" dependencies = [ "bitflags 1.3.2", "serde", @@ -2366,6 +2336,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.5" @@ -2427,10 +2406,9 @@ checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] name = "nargo" -version = "0.18.0" +version = "0.19.2" dependencies = [ "acvm", - "base64", "codespan-reporting", "fm", "iter-extended", @@ -2440,6 +2418,7 @@ dependencies = [ "noirc_evaluator", "noirc_frontend", "noirc_printable_type", + "rayon", "rustc_version", "serde", "thiserror", @@ -2447,7 +2426,7 @@ dependencies = [ [[package]] name = "nargo_cli" -version = "0.18.0" +version = "0.19.2" dependencies = [ "acvm", "assert_cmd", @@ -2495,7 +2474,7 @@ dependencies = [ [[package]] name = "nargo_fmt" -version = "0.18.0" +version = "0.19.2" dependencies = [ "bytecount", "noirc_frontend", @@ -2507,12 +2486,13 @@ dependencies = [ [[package]] name = "nargo_toml" -version = "0.18.0" +version = "0.19.2" dependencies = [ "dirs", "fm", "nargo", "noirc_frontend", + "semver", "serde", "thiserror", "toml", @@ -2555,12 +2535,13 @@ dependencies = [ [[package]] name = "noir_debugger" -version = "0.18.0" +version = "0.19.2" dependencies = [ "acvm", "codespan-reporting", "easy-repl", "nargo", + "noirc_errors", "noirc_printable_type", "owo-colors", "thiserror", @@ -2568,14 +2549,15 @@ dependencies = [ [[package]] name = "noir_lsp" -version = "0.18.0" +version = "0.19.2" dependencies = [ "acvm", "async-lsp", "cfg-if", "codespan-lsp", "codespan-reporting", - "lsp-types 0.94.0", + "fm", + "lsp-types 0.94.1", "nargo", "nargo_toml", "noirc_driver", @@ -2583,6 +2565,7 @@ dependencies = [ "noirc_frontend", "serde", "serde_json", + "serde_with", "tokio", "tower", "wasm-bindgen", @@ -2590,7 +2573,7 @@ dependencies = [ [[package]] name = "noir_wasm" -version = "0.18.0" +version = "0.19.2" dependencies = [ "acvm", "build-data", @@ -2612,7 +2595,7 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "0.18.0" +version = "0.19.2" dependencies = [ "acvm", "iter-extended", @@ -2629,7 +2612,7 @@ dependencies = [ [[package]] name = "noirc_abi_wasm" -version = "0.18.0" +version = "0.19.2" dependencies = [ "acvm", "build-data", @@ -2646,14 +2629,14 @@ dependencies = [ [[package]] name = "noirc_driver" -version = "0.18.0" +version = "0.19.2" dependencies = [ "acvm", - "base64", "build-data", "clap", "fm", "fxhash", + "iter-extended", "noirc_abi", "noirc_errors", "noirc_evaluator", @@ -2663,7 +2646,7 @@ dependencies = [ [[package]] name = "noirc_errors" -version = "0.18.0" +version = "0.19.2" dependencies = [ "acvm", "chumsky", @@ -2676,22 +2659,22 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "0.18.0" +version = "0.19.2" dependencies = [ "acvm", "fxhash", "im", "iter-extended", - "noirc_abi", "noirc_errors", "noirc_frontend", "num-bigint", + "serde", "thiserror", ] [[package]] name = "noirc_frontend" -version = "0.18.0" +version = "0.19.2" dependencies = [ "acvm", "arena", @@ -2713,7 +2696,7 @@ dependencies = [ [[package]] name = "noirc_printable_type" -version = "0.18.0" +version = "0.19.2" dependencies = [ "acvm", "iter-extended", @@ -3078,19 +3061,19 @@ dependencies = [ [[package]] name = "proptest" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" dependencies = [ "bit-set", - "bitflags 1.3.2", - "byteorder", + "bit-vec", + "bitflags 2.3.3", "lazy_static", "num-traits", "rand", "rand_chacha", "rand_xorshift", - "regex-syntax 0.6.29", + "regex-syntax", "rusty-fork", "tempfile", "unarray", @@ -3274,7 +3257,7 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata 0.3.3", - "regex-syntax 0.7.4", + "regex-syntax", ] [[package]] @@ -3291,15 +3274,9 @@ checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.4", + "regex-syntax", ] -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - [[package]] name = "regex-syntax" version = "0.7.4" @@ -3487,20 +3464,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.37.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - [[package]] name = "rustix" version = "0.38.4" @@ -3510,7 +3473,7 @@ dependencies = [ "bitflags 2.3.3", "errno", "libc", - "linux-raw-sys 0.4.3", + "linux-raw-sys", "windows-sys 0.48.0", ] @@ -3707,20 +3670,26 @@ dependencies = [ "zeroize", ] +[[package]] +name = "self_cell" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6" + [[package]] name = "semver" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.171" +version = "1.0.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +checksum = "0a5bf42b8d227d4abf38a1ddb08602e229108a517cd4e5bb28f9c7eaafdce5c0" dependencies = [ "serde_derive", ] @@ -3763,9 +3732,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.171" +version = "1.0.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +checksum = "741e124f5485c7e60c03b043f79f320bff3527f4bbf12cf3831750dc46a0ec2c" dependencies = [ "proc-macro2", "quote", @@ -3774,9 +3743,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.103" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -3874,6 +3843,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared-buffer" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cf61602ee61e2f83dd016b3e6387245291cf728ea071c378b35088125b4d995" +dependencies = [ + "bytes", + "memmap2 0.6.2", +] + [[package]] name = "shell-words" version = "1.1.0" @@ -4074,7 +4053,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "167a4ffd7c35c143fd1030aa3c2caf76ba42220bd5a6b5f4781896434723b8c3" dependencies = [ "debugid", - "memmap2", + "memmap2 0.5.10", "stable_deref_trait", "uuid", ] @@ -4137,15 +4116,14 @@ checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" [[package]] name = "tempfile" -version = "3.6.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ - "autocfg", "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.23", + "rustix", "windows-sys 0.48.0", ] @@ -4587,7 +4565,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54f8c3c56044fc359f905b72879576a15d49c46d085ed6266a98826716f14033" dependencies = [ - "rustix 0.38.4", + "rustix", "windows-sys 0.48.0", ] @@ -4733,9 +4711,9 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.33.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39de0723a53d3c8f54bed106cfbc0d06b3e4d945c5c5022115a61e3b29183ae" +checksum = "1ba64e81215916eaeb48fee292f29401d69235d62d8b8fd92a7b2844ec5ae5f7" dependencies = [ "leb128", ] @@ -4753,9 +4731,9 @@ dependencies = [ [[package]] name = "wasmer" -version = "3.3.0" +version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78caedecd8cb71ed47ccca03b68d69414a3d278bb031e6f93f15759344efdd52" +checksum = "50cb1ae2956aac1fbbcf334c543c1143cdf7d5b0a5fb6c3d23a17bf37dd1f47b" dependencies = [ "bytes", "cfg-if", @@ -4766,6 +4744,7 @@ dependencies = [ "rustc-demangle", "serde", "serde-wasm-bindgen", + "shared-buffer", "target-lexicon", "thiserror", "wasm-bindgen", @@ -4783,19 +4762,23 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "3.3.0" +version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726a8450541af4a57c34af7b6973fdbfc79f896cc7e733429577dfd1d1687180" +checksum = "12fd9aeef339095798d1e04957d5657d97490b1112f145cbf08b98f6393b4a0a" dependencies = [ "backtrace", + "bytes", "cfg-if", "enum-iterator", "enumset", "lazy_static", "leb128", - "memmap2", + "memmap2 0.5.10", "more-asserts", "region", + "rkyv", + "self_cell", + "shared-buffer", "smallvec", "thiserror", "wasmer-types", @@ -4806,9 +4789,9 @@ dependencies = [ [[package]] name = "wasmer-compiler-cranelift" -version = "3.3.0" +version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e5633f90f372563ebbdf3f9799c7b29ba11c90e56cf9b54017112d2e656c95" +checksum = "344f5f1186c122756232fe7f156cc8d2e7bf333d5a658e81e25efa3415c26d07" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -4825,9 +4808,9 @@ dependencies = [ [[package]] name = "wasmer-derive" -version = "3.3.0" +version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97901fdbaae383dbb90ea162cc3a76a9fa58ac39aec7948b4c0b9bbef9307738" +checksum = "2ac8c1f2dc0ed3c7412a5546e468365184a461f8ce7dfe2a707b621724339f91" dependencies = [ "proc-macro-error", "proc-macro2", @@ -4837,9 +4820,9 @@ dependencies = [ [[package]] name = "wasmer-types" -version = "3.3.0" +version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67f1f2839f4f61509550e4ddcd0e658e19f3af862b51c79fda15549d735d659b" +checksum = "5a57ecbf218c0a9348d4dfbdac0f9d42d9201ae276dffb13e61ea4ff939ecce7" dependencies = [ "bytecheck", "enum-iterator", @@ -4853,14 +4836,15 @@ dependencies = [ [[package]] name = "wasmer-vm" -version = "3.3.0" +version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043118ec4f16d1714fed3aab758b502b864bd865e1d5188626c9ad290100563f" +checksum = "60c3513477bc0097250f6e34a640e2a903bb0ee57e6bb518c427f72c06ac7728" dependencies = [ "backtrace", "cc", "cfg-if", "corosensei", + "crossbeam-queue", "dashmap", "derivative", "enum-iterator", @@ -4896,9 +4880,9 @@ dependencies = [ [[package]] name = "wast" -version = "65.0.1" +version = "64.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd8c1cbadf94a0b0d1071c581d3cfea1b7ed5192c79808dd15406e508dd0afb" +checksum = "a259b226fd6910225aa7baeba82f9d9933b6d00f2ce1b49b80fa4214328237cc" dependencies = [ "leb128", "memchr", @@ -4908,9 +4892,9 @@ dependencies = [ [[package]] name = "wat" -version = "1.0.73" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3209e35eeaf483714f4c6be93f4a03e69aad5f304e3fa66afa7cb90fe1c8051f" +checksum = "53253d920ab413fca1c7dc2161d601c79b4fdf631d0ba51dd4343bf9b556c3f6" dependencies = [ "wast", ] @@ -4963,10 +4947,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "af6041b3f84485c21b57acdc0fee4f4f0c93f426053dc05fa5d6fc262537bbff" dependencies = [ "windows-targets 0.48.1", ] diff --git a/Cargo.toml b/Cargo.toml index 78b15287060..bc2c4e9f73e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ resolver = "2" [workspace.package] # x-release-please-start-version -version = "0.18.0" +version = "0.19.2" # x-release-please-end authors = ["The Noir Team "] edition = "2021" @@ -47,9 +47,29 @@ license = "MIT OR Apache-2.0" 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 } + +# Noir compiler workspace dependencies arena = { path = "compiler/utils/arena" } fm = { path = "compiler/fm" } iter-extended = { path = "compiler/utils/iter-extended" } +noirc_driver = { path = "compiler/noirc_driver" } +noirc_errors = { path = "compiler/noirc_errors" } +noirc_evaluator = { path = "compiler/noirc_evaluator" } +noirc_frontend = { path = "compiler/noirc_frontend" } +noirc_printable_type = { path = "compiler/noirc_printable_type" } +noir_wasm = { path = "compiler/wasm" } + +# Noir tooling workspace dependencies nargo = { path = "tooling/nargo" } nargo_fmt = { path = "tooling/nargo_fmt" } nargo_cli = { path = "tooling/nargo_cli" } @@ -58,12 +78,22 @@ noir_lsp = { path = "tooling/lsp" } noir_debugger = { path = "tooling/debugger" } noirc_abi = { path = "tooling/noirc_abi" } bb_abstraction_leaks = { path = "tooling/bb_abstraction_leaks" } -noirc_driver = { path = "compiler/noirc_driver" } -noirc_errors = { path = "compiler/noirc_errors" } -noirc_evaluator = { path = "compiler/noirc_evaluator" } -noirc_frontend = { path = "compiler/noirc_frontend" } -noirc_printable_type = { path = "compiler/noirc_printable_type" } -noir_wasm = { path = "compiler/wasm" } + +# LSP +async-lsp = { version = "0.1.0", default-features = false } +lsp-types = "0.94.1" +tower = "0.4" + +# Wasm +wasm-bindgen = { version = "=0.2.86", features = ["serde-serialize"] } +wasm-bindgen-test = "0.3.36" +wasm-bindgen-futures = "0.4.36" +console_error_panic_hook = "0.1.7" +gloo-utils = { version = "0.1", features = ["serde"] } +js-sys = "0.3.62" +getrandom = "0.2" + + cfg-if = "1.0.0" clap = { version = "4.3.19", features = ["derive"] } codespan = { version = "0.11.1", features = ["serialization"] } @@ -74,31 +104,18 @@ chumsky = { git = "https://github.com/jfecher/chumsky", rev = "ad9d312", default "std", ] } dirs = "4" -lsp-types = "0.94" serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0" smol_str = { version = "0.1.17", features = ["serde"] } thiserror = "1.0.21" toml = "0.7.2" -tower = "0.4" url = "2.2.0" -wasm-bindgen = { version = "=0.2.86", features = ["serde-serialize"] } -wasm-bindgen-test = "0.3.33" -js-sys = "0.3.62" base64 = "0.21.2" fxhash = "0.2.1" -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 } - +build-data = "0.1.3" bincode = "1.3.3" - hex = "0.4.2" +const_format = "0.2.30" num-bigint = "0.4" num-traits = "0.2" diff --git a/README.md b/README.md index 22ace1fd3b4..c48c9110187 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Concretely the following items are on the road map: ## Minimum Rust version -This crate's minimum supported rustc version is 1.66.0. +This crate's minimum supported rustc version is 1.71.1. ## Working on this project diff --git a/acvm-repo/CHANGELOG.md b/acvm-repo/CHANGELOG.md index b187addf7b7..3eb4e9146c6 100644 --- a/acvm-repo/CHANGELOG.md +++ b/acvm-repo/CHANGELOG.md @@ -5,6 +5,147 @@ 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.33.0](https://github.com/noir-lang/noir/compare/v0.32.0...v0.33.0) (2023-11-07) + + +### ⚠ 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)) +* 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.32.0](https://github.com/noir-lang/noir/compare/v0.31.0...v0.32.0) (2023-11-07) + + +### ⚠ 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)) +* 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.31.0](https://github.com/noir-lang/noir/compare/v0.30.0...v0.31.0) (2023-11-02) + + +### ⚠ 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)) +* 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.30.0](https://github.com/noir-lang/noir/compare/v0.29.0...v0.30.0) (2023-10-25) diff --git a/acvm-repo/acir/Cargo.toml b/acvm-repo/acir/Cargo.toml index af6429a3a3d..25d770e1f17 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.30.0" +version = "0.33.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -19,6 +19,7 @@ serde.workspace = true thiserror.workspace = true flate2 = "1.0.24" bincode.workspace = true +base64.workspace = true [dev-dependencies] serde_json = "1.0" diff --git a/acvm-repo/acir/src/circuit/mod.rs b/acvm-repo/acir/src/circuit/mod.rs index 3171cb57d16..99ab389e31e 100644 --- a/acvm-repo/acir/src/circuit/mod.rs +++ b/acvm-repo/acir/src/circuit/mod.rs @@ -9,9 +9,10 @@ use thiserror::Error; use std::{io::prelude::*, num::ParseIntError, str::FromStr}; +use base64::Engine; use flate2::Compression; +use serde::{de::Error as DeserializationError, Deserialize, Deserializer, Serialize, Serializer}; -use serde::{Deserialize, Serialize}; use std::collections::BTreeSet; #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Default)] @@ -125,7 +126,7 @@ impl Circuit { PublicInputs(public_inputs) } - pub fn write(&self, writer: W) -> std::io::Result<()> { + fn write(&self, writer: W) -> std::io::Result<()> { let buf = bincode::serialize(self).unwrap(); let mut encoder = flate2::write::GzEncoder::new(writer, Compression::default()); encoder.write_all(&buf)?; @@ -133,13 +134,46 @@ impl Circuit { Ok(()) } - pub fn read(reader: R) -> std::io::Result { + fn read(reader: R) -> std::io::Result { let mut gz_decoder = flate2::read::GzDecoder::new(reader); let mut buf_d = Vec::new(); gz_decoder.read_to_end(&mut buf_d)?; bincode::deserialize(&buf_d) .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err)) } + + pub fn serialize_circuit(circuit: &Circuit) -> Vec { + let mut circuit_bytes: Vec = Vec::new(); + circuit.write(&mut circuit_bytes).expect("expected circuit to be serializable"); + circuit_bytes + } + + pub fn deserialize_circuit(serialized_circuit: &[u8]) -> std::io::Result { + Circuit::read(serialized_circuit) + } + + // Serialize and base64 encode circuit + pub fn serialize_circuit_base64(circuit: &Circuit, s: S) -> Result + where + S: Serializer, + { + let circuit_bytes = Circuit::serialize_circuit(circuit); + let encoded_b64 = base64::engine::general_purpose::STANDARD.encode(circuit_bytes); + s.serialize_str(&encoded_b64) + } + + // Deserialize and base64 decode circuit + pub fn deserialize_circuit_base64<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let bytecode_b64: String = serde::Deserialize::deserialize(deserializer)?; + let circuit_bytes = base64::engine::general_purpose::STANDARD + .decode(bytecode_b64) + .map_err(D::Error::custom)?; + let circuit = Self::deserialize_circuit(&circuit_bytes).map_err(D::Error::custom)?; + Ok(circuit) + } } impl std::fmt::Display for Circuit { @@ -229,9 +263,8 @@ mod tests { }; fn read_write(circuit: Circuit) -> (Circuit, Circuit) { - let mut bytes = Vec::new(); - circuit.write(&mut bytes).unwrap(); - let got_circuit = Circuit::read(&*bytes).unwrap(); + let bytes = Circuit::serialize_circuit(&circuit); + let got_circuit = Circuit::deserialize_circuit(&bytes).unwrap(); (circuit, got_circuit) } @@ -277,7 +310,7 @@ mod tests { encoder.write_all(bad_circuit).unwrap(); encoder.finish().unwrap(); - let deserialization_result = Circuit::read(&*zipped_bad_circuit); + let deserialization_result = Circuit::deserialize_circuit(&zipped_bad_circuit); assert!(deserialization_result.is_err()); } } diff --git a/acvm-repo/acir/tests/test_program_serialization.rs b/acvm-repo/acir/tests/test_program_serialization.rs index 2a25129df48..ff69ba34437 100644 --- a/acvm-repo/acir/tests/test_program_serialization.rs +++ b/acvm-repo/acir/tests/test_program_serialization.rs @@ -42,8 +42,7 @@ fn addition_circuit() { ..Circuit::default() }; - let mut bytes = Vec::new(); - circuit.write(&mut bytes).unwrap(); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 144, 187, 13, 192, 32, 12, 68, 249, 100, 32, 27, @@ -73,8 +72,7 @@ fn fixed_base_scalar_mul_circuit() { ..Circuit::default() }; - let mut bytes = Vec::new(); - circuit.write(&mut bytes).unwrap(); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 138, 91, 10, 0, 48, 12, 194, 178, 215, 215, 46, 189, @@ -101,8 +99,7 @@ fn pedersen_circuit() { ..Circuit::default() }; - let mut bytes = Vec::new(); - circuit.write(&mut bytes).unwrap(); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 138, 9, 10, 0, 64, 8, 2, 103, 15, 250, 255, 139, @@ -143,8 +140,7 @@ fn schnorr_verify_circuit() { ..Circuit::default() }; - let mut bytes = Vec::new(); - circuit.write(&mut bytes).unwrap(); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 77, 210, 87, 78, 2, 1, 20, 134, 209, 177, 247, 222, 123, @@ -197,8 +193,7 @@ fn simple_brillig_foreign_call() { ..Circuit::default() }; - let mut bytes = Vec::new(); - circuit.write(&mut bytes).unwrap(); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 143, 49, 10, 64, 33, 12, 67, 99, 63, 124, 60, 142, @@ -271,8 +266,7 @@ fn complex_brillig_foreign_call() { ..Circuit::default() }; - let mut bytes = Vec::new(); - circuit.write(&mut bytes).unwrap(); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 83, 219, 10, 128, 48, 8, 117, 174, 139, 159, 179, @@ -310,8 +304,7 @@ fn memory_op_circuit() { return_values: PublicInputs([Witness(4)].into()), ..Circuit::default() }; - let mut bytes = Vec::new(); - circuit.write(&mut bytes).unwrap(); + let bytes = Circuit::serialize_circuit(&circuit); let expected_serialization: Vec = vec![ 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 146, 49, 14, 0, 32, 8, 3, 139, 192, 127, 240, 7, diff --git a/acvm-repo/acir_field/Cargo.toml b/acvm-repo/acir_field/Cargo.toml index 22ec76ff764..2cd2801db10 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.30.0" +version = "0.33.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acvm/Cargo.toml b/acvm-repo/acvm/Cargo.toml index d52d39e1285..032d93230da 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.30.0" +version = "0.33.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/acvm/src/pwg/brillig.rs b/acvm-repo/acvm/src/pwg/brillig.rs index b0e5ec6dd48..0db38c776e2 100644 --- a/acvm-repo/acvm/src/pwg/brillig.rs +++ b/acvm-repo/acvm/src/pwg/brillig.rs @@ -112,6 +112,22 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { Ok(Self { vm, acir_index }) } + pub fn get_registers(&self) -> &Registers { + self.vm.get_registers() + } + + pub fn set_register(&mut self, register_index: usize, value: Value) { + self.vm.set_register(RegisterIndex(register_index), value); + } + + pub fn get_memory(&self) -> &[Value] { + self.vm.get_memory() + } + + pub fn write_memory_at(&mut self, ptr: usize, value: Value) { + self.vm.write_memory_at(ptr, value); + } + pub(super) fn solve(&mut self) -> Result { let status = self.vm.process_opcodes(); self.handle_vm_status(status) diff --git a/acvm-repo/acvm/src/pwg/mod.rs b/acvm-repo/acvm/src/pwg/mod.rs index 1022ad13800..c1edf60161a 100644 --- a/acvm-repo/acvm/src/pwg/mod.rs +++ b/acvm-repo/acvm/src/pwg/mod.rs @@ -168,6 +168,14 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { &self.witness_map } + pub fn overwrite_witness( + &mut self, + witness: Witness, + value: FieldElement, + ) -> Option { + self.witness_map.insert(witness, value) + } + /// Returns a slice containing the opcodes of the circuit being executed. pub fn opcodes(&self) -> &[Opcode] { self.opcodes @@ -193,6 +201,10 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { status } + pub fn get_status(&self) -> &ACVMStatus { + &self.status + } + /// Sets the VM status to [ACVMStatus::Failure] using the provided `error`. /// Returns the new status. fn fail(&mut self, error: OpcodeResolutionError) -> ACVMStatus { diff --git a/acvm-repo/acvm_js/Cargo.toml b/acvm-repo/acvm_js/Cargo.toml index b63b0b7be6e..e287ac9ed17 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.30.0" +version = "0.33.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -21,22 +21,23 @@ cfg-if = "1.0.0" [target.'cfg(target_arch = "wasm32")'.dependencies] acvm = { path = "../acvm", default-features = false } barretenberg_blackbox_solver = { path = "../barretenberg_blackbox_solver", default-features = false } -wasm-bindgen = { version = "0.2.86", features = ["serde-serialize"] } -wasm-bindgen-futures = "0.4.36" +wasm-bindgen.workspace = true +wasm-bindgen-futures.workspace = true +console_error_panic_hook.workspace = true +gloo-utils.workspace = true +js-sys.workspace = true + serde = { version = "1.0.136", features = ["derive"] } log = "0.4.17" wasm-logger = "0.2.0" -console_error_panic_hook = "0.1.7" -gloo-utils = { version = "0.1", features = ["serde"] } -js-sys.workspace = true const-str = "0.5.5" [build-dependencies] -build-data = "0.1.3" +build-data.workspace = true pkg-config = "0.3" [dev-dependencies] -wasm-bindgen-test = "0.3.36" +wasm-bindgen-test.workspace = true [features] default = ["bn254"] diff --git a/acvm-repo/acvm_js/package.json b/acvm-repo/acvm_js/package.json index 4947fee5ad8..19090022e25 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.30.0", + "version": "0.33.0", "repository": { "type": "git", "url": "https://github.com/noir-lang/acvm.git" diff --git a/acvm-repo/acvm_js/src/execute.rs b/acvm-repo/acvm_js/src/execute.rs index ebbfc4297c3..81e2a11ed5a 100644 --- a/acvm-repo/acvm_js/src/execute.rs +++ b/acvm-repo/acvm_js/src/execute.rs @@ -64,7 +64,8 @@ pub async fn execute_circuit_with_black_box_solver( foreign_call_handler: ForeignCallHandler, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = Circuit::read(&*circuit).expect("Failed to deserialize circuit"); + let circuit: Circuit = + Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); let mut acvm = ACVM::new(&solver.0, &circuit.opcodes, initial_witness.into()); diff --git a/acvm-repo/acvm_js/src/public_witness.rs b/acvm-repo/acvm_js/src/public_witness.rs index 46e4b788772..8dc66c435b3 100644 --- a/acvm-repo/acvm_js/src/public_witness.rs +++ b/acvm-repo/acvm_js/src/public_witness.rs @@ -30,7 +30,8 @@ pub fn get_return_witness( witness_map: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = Circuit::read(&*circuit).expect("Failed to deserialize circuit"); + let circuit: Circuit = + Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); let witness_map = WitnessMap::from(witness_map); let return_witness = @@ -50,7 +51,8 @@ pub fn get_public_parameters_witness( solved_witness: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = Circuit::read(&*circuit).expect("Failed to deserialize circuit"); + let circuit: Circuit = + Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); let witness_map = WitnessMap::from(solved_witness); let public_params_witness = @@ -70,7 +72,8 @@ pub fn get_public_witness( solved_witness: JsWitnessMap, ) -> Result { console_error_panic_hook::set_once(); - let circuit: Circuit = Circuit::read(&*circuit).expect("Failed to deserialize circuit"); + let circuit: Circuit = + Circuit::deserialize_circuit(&circuit).expect("Failed to deserialize circuit"); let witness_map = WitnessMap::from(solved_witness); let public_witness = diff --git a/acvm-repo/barretenberg_blackbox_solver/Cargo.toml b/acvm-repo/barretenberg_blackbox_solver/Cargo.toml index c189c11cd10..6917e7fbf81 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.30.0" +version = "0.33.0" # x-release-please-end authors.workspace = true edition.workspace = true @@ -30,17 +30,17 @@ ark-ff = { version = "^0.4.0", default-features = false } num-bigint.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] -wasmer = { version = "3.3", default-features = false, features = [ +wasmer = { version = "4.2.3", default-features = false, features = [ "js-default", ] } -getrandom = { version = "0.2", features = ["js"] } -wasm-bindgen-futures = "0.4.36" +getrandom = { workspace = true, features = ["js"] } +wasm-bindgen-futures.workspace = true js-sys.workspace = true [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -getrandom = "0.2" -wasmer = "3.3" +getrandom.workspace = true +wasmer = "4.2.3" [build-dependencies] pkg-config = "0.3" diff --git a/acvm-repo/barretenberg_blackbox_solver/src/wasm/pedersen.rs b/acvm-repo/barretenberg_blackbox_solver/src/wasm/pedersen.rs index c19554eb6bc..c816e5b4d1b 100644 --- a/acvm-repo/barretenberg_blackbox_solver/src/wasm/pedersen.rs +++ b/acvm-repo/barretenberg_blackbox_solver/src/wasm/pedersen.rs @@ -57,8 +57,7 @@ impl Pedersen for Barretenberg { #[test] fn pedersen_hash_to_point() -> Result<(), Error> { let barretenberg = Barretenberg::new(); - let (x, y) = barretenberg - .encrypt(vec![FieldElement::from(1 as u128), FieldElement::from(1 as u128)], 1)?; + let (x, y) = barretenberg.encrypt(vec![FieldElement::one(), FieldElement::one()], 1)?; let expected_x = FieldElement::from_hex( "0x12afb43195f5c621d1d2cabb5f629707095c5307fd4185a663d4e80bb083e878", ) diff --git a/acvm-repo/blackbox_solver/Cargo.toml b/acvm-repo/blackbox_solver/Cargo.toml index 5e9646969e4..ad0862afe4f 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.30.0" +version = "0.33.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 7a2592d6d32..542839a5767 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.30.0" +version = "0.33.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 ac826585b5c..2d89aa7aa15 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.30.0" +version = "0.33.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/acvm-repo/brillig_vm/src/lib.rs b/acvm-repo/brillig_vm/src/lib.rs index e0d30f7b2e0..482b9b36d77 100644 --- a/acvm-repo/brillig_vm/src/lib.rs +++ b/acvm-repo/brillig_vm/src/lib.rs @@ -164,10 +164,18 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { &self.registers } + pub fn set_register(&mut self, register_index: RegisterIndex, value: Value) { + self.registers.set(register_index, value); + } + pub fn get_memory(&self) -> &Vec { self.memory.values() } + pub fn write_memory_at(&mut self, ptr: usize, value: Value) { + self.memory.write(ptr, value); + } + /// Process a single opcode and modify the program counter. pub fn process_opcode(&mut self) -> VMStatus { let opcode = &self.bytecode[self.program_counter]; diff --git a/acvm-repo/stdlib/Cargo.toml b/acvm-repo/stdlib/Cargo.toml index daba0fe9bba..63a8b71eb15 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.30.0" +version = "0.33.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/compiler/integration-tests/circuits/main/Nargo.toml b/compiler/integration-tests/circuits/main/Nargo.toml index 664e817cc84..cc5a0a357fa 100644 --- a/compiler/integration-tests/circuits/main/Nargo.toml +++ b/compiler/integration-tests/circuits/main/Nargo.toml @@ -2,6 +2,4 @@ name = "main" type = "bin" authors = [""] -compiler_version = "0.9.0" - [dependencies] diff --git a/compiler/integration-tests/circuits/main/src/main.nr b/compiler/integration-tests/circuits/main/src/main.nr index 6e170de75fc..4e1fd3c9035 100644 --- a/compiler/integration-tests/circuits/main/src/main.nr +++ b/compiler/integration-tests/circuits/main/src/main.nr @@ -1,3 +1,3 @@ -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { assert(x != y); } diff --git a/compiler/integration-tests/circuits/recursion/Nargo.toml b/compiler/integration-tests/circuits/recursion/Nargo.toml index 5469c07c7de..276ba1b34e0 100644 --- a/compiler/integration-tests/circuits/recursion/Nargo.toml +++ b/compiler/integration-tests/circuits/recursion/Nargo.toml @@ -2,6 +2,4 @@ name = "recursion" type = "bin" authors = [""] -compiler_version = "0.9.0" - [dependencies] diff --git a/compiler/integration-tests/circuits/recursion/src/main.nr b/compiler/integration-tests/circuits/recursion/src/main.nr index ffa3ccef90e..7cf956d1950 100644 --- a/compiler/integration-tests/circuits/recursion/src/main.nr +++ b/compiler/integration-tests/circuits/recursion/src/main.nr @@ -1,20 +1,14 @@ 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]{ + 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 - ) + std::verify_proof(vk, p, pi, key_hash, input_aggregation_object) } 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 f2063c5e4b0..95a1aa502ad 100644 --- a/compiler/integration-tests/test/browser/compile_prove_verify.test.ts +++ b/compiler/integration-tests/test/browser/compile_prove_verify.test.ts @@ -3,7 +3,7 @@ import { Logger } from 'tslog'; import * as TOML from 'smol-toml'; import { initializeResolver } from '@noir-lang/source-resolver'; -import newCompiler, { compile, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm'; +import newCompiler, { CompiledProgram, 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'; @@ -32,7 +32,7 @@ const suite = Mocha.Suite.create(mocha.suite, 'Noir end to end test'); suite.timeout(60 * 20e3); //20mins -async function getCircuit(noirSource: string) { +function getCircuit(noirSource: string): CompiledProgram { // eslint-disable-next-line @typescript-eslint/no-unused-vars initializeResolver((id: string) => { logger.debug('source-resolver: resolving:', id); @@ -40,7 +40,12 @@ async function getCircuit(noirSource: string) { }); // We're ignoring this in the resolver but pass in something sensible. - return compile('/main.nr'); + const result = compile('/main.nr'); + if (!('program' in result)) { + throw new Error('Compilation failed'); + } + + return result.program; } test_cases.forEach((testInfo) => { @@ -51,11 +56,11 @@ test_cases.forEach((testInfo) => { const noir_source = await getFile(`${base_relative_path}/${test_case}/src/main.nr`); - let noir_program; + let noir_program: CompiledProgram; try { - noir_program = await getCircuit(noir_source); + noir_program = getCircuit(noir_source); - expect(await noir_program, 'Compile output ').to.be.an('object'); + expect(noir_program, 'Compile output ').to.be.an('object'); } catch (e) { expect(e, 'Compilation Step').to.not.be.an('error'); throw e; diff --git a/compiler/integration-tests/test/browser/recursion.test.ts b/compiler/integration-tests/test/browser/recursion.test.ts index 6a5592bca67..dbf74882654 100644 --- a/compiler/integration-tests/test/browser/recursion.test.ts +++ b/compiler/integration-tests/test/browser/recursion.test.ts @@ -3,7 +3,7 @@ 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, { compile, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm'; +import newCompiler, { CompiledProgram, 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'; @@ -26,7 +26,7 @@ const base_relative_path = '../../../../..'; const circuit_main = 'compiler/integration-tests/circuits/main'; const circuit_recursion = 'compiler/integration-tests/circuits/recursion'; -async function getCircuit(noirSource: string) { +function getCircuit(noirSource: string): CompiledProgram { // eslint-disable-next-line @typescript-eslint/no-unused-vars initializeResolver((id: string) => { logger.debug('source-resolver: resolving:', id); @@ -34,7 +34,12 @@ async function getCircuit(noirSource: string) { }); // We're ignoring this in the resolver but pass in something sensible. - return compile('./main.nr'); + const result = compile('/main.nr'); + if (!('program' in result)) { + throw new Error('Compilation failed'); + } + + return result.program; } describe('It compiles noir program code, receiving circuit bytes and abi object.', () => { @@ -50,7 +55,7 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. }); it('Should generate valid inner proof for correct input, then verify proof within a proof', async () => { - const main_program = await getCircuit(circuit_main_source); + const main_program = getCircuit(circuit_main_source); const main_inputs: InputMap = TOML.parse(circuit_main_toml) as InputMap; const main_backend = new BarretenbergBackend(main_program); 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 038c692220f..738bc2df8dd 100644 --- a/compiler/integration-tests/test/node/smart_contract_verifier.test.ts +++ b/compiler/integration-tests/test/node/smart_contract_verifier.test.ts @@ -33,7 +33,12 @@ test_cases.forEach((testInfo) => { const noir_source_path = resolve(`${base_relative_path}/${test_case}/src/main.nr`); - const noir_program = compile(noir_source_path); + const compileResult = compile(noir_source_path); + if (!('program' in compileResult)) { + throw new Error('Compilation failed'); + } + + const noir_program = compileResult.program; const backend = new BarretenbergBackend(noir_program); const program = new Noir(noir_program, backend); diff --git a/compiler/noirc_driver/Cargo.toml b/compiler/noirc_driver/Cargo.toml index f1c120e1687..09044b39323 100644 --- a/compiler/noirc_driver/Cargo.toml +++ b/compiler/noirc_driver/Cargo.toml @@ -8,7 +8,7 @@ license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] -build-data = "0.1.3" +build-data.workspace = true [dependencies] clap.workspace = true @@ -17,7 +17,7 @@ noirc_frontend.workspace = true noirc_evaluator.workspace = true noirc_abi.workspace = true acvm.workspace = true +iter-extended.workspace = true fm.workspace = true serde.workspace = true -base64.workspace = true fxhash.workspace = true diff --git a/compiler/noirc_driver/build.rs b/compiler/noirc_driver/build.rs index 7b5a645c026..6bef7f1fda7 100644 --- a/compiler/noirc_driver/build.rs +++ b/compiler/noirc_driver/build.rs @@ -1,9 +1,6 @@ const GIT_COMMIT: &&str = &"GIT_COMMIT"; fn main() { - // Rebuild if the tests have changed - println!("cargo:rerun-if-changed=tests"); - // Only use build_data if the environment variable isn't set // The environment variable is always set when working via Nix if std::env::var(GIT_COMMIT).is_err() { diff --git a/compiler/noirc_driver/src/abi_gen.rs b/compiler/noirc_driver/src/abi_gen.rs new file mode 100644 index 00000000000..a4835338f16 --- /dev/null +++ b/compiler/noirc_driver/src/abi_gen.rs @@ -0,0 +1,141 @@ +use std::collections::BTreeMap; + +use acvm::acir::native_types::Witness; +use iter_extended::{btree_map, vecmap}; +use noirc_abi::{Abi, AbiParameter, AbiType}; +use noirc_frontend::{ + hir::Context, + hir_def::{function::Param, stmt::HirPattern}, + node_interner::{FuncId, NodeInterner}, +}; +use std::ops::Range; + +/// Arranges a function signature and a generated circuit's return witnesses into a +/// `noirc_abi::Abi`. +pub(super) fn gen_abi( + context: &Context, + func_id: &FuncId, + input_witnesses: Vec, + return_witnesses: Vec, +) -> Abi { + let (parameters, return_type) = compute_function_abi(context, func_id); + let param_witnesses = param_witnesses_from_abi_param(¶meters, input_witnesses); + Abi { parameters, return_type, param_witnesses, return_witnesses } +} + +pub(super) fn compute_function_abi( + context: &Context, + func_id: &FuncId, +) -> (Vec, Option) { + let func_meta = context.def_interner.function_meta(func_id); + + let (parameters, return_type) = func_meta.into_function_signature(); + let parameters = into_abi_params(context, parameters); + let return_type = return_type.map(|typ| AbiType::from_type(context, &typ)); + (parameters, return_type) +} + +/// Attempts to retrieve the name of this parameter. Returns None +/// if this parameter is a tuple or struct pattern. +fn get_param_name<'a>(pattern: &HirPattern, interner: &'a NodeInterner) -> Option<&'a str> { + match pattern { + HirPattern::Identifier(ident) => Some(interner.definition_name(ident.id)), + HirPattern::Mutable(pattern, _) => get_param_name(pattern, interner), + HirPattern::Tuple(_, _) => None, + HirPattern::Struct(_, _, _) => None, + } +} + +fn into_abi_params(context: &Context, params: Vec) -> Vec { + vecmap(params, |(pattern, typ, vis)| { + let param_name = get_param_name(&pattern, &context.def_interner) + .expect("Abi for tuple and struct parameters is unimplemented") + .to_owned(); + let as_abi = AbiType::from_type(context, &typ); + AbiParameter { name: param_name, typ: as_abi, visibility: vis.into() } + }) +} + +// Takes each abi parameter and shallowly maps to the expected witness range in which the +// parameter's constituent values live. +fn param_witnesses_from_abi_param( + abi_params: &Vec, + input_witnesses: Vec, +) -> BTreeMap>> { + let mut idx = 0_usize; + if input_witnesses.is_empty() { + return BTreeMap::new(); + } + + btree_map(abi_params, |param| { + let num_field_elements_needed = param.typ.field_count() as usize; + let param_witnesses = &input_witnesses[idx..idx + num_field_elements_needed]; + + // It's likely that `param_witnesses` will consist of mostly incrementing witness indices. + // We then want to collapse these into `Range`s to save space. + let param_witnesses = collapse_ranges(param_witnesses); + idx += num_field_elements_needed; + (param.name.clone(), param_witnesses) + }) +} + +/// Takes a vector of [`Witnesses`][`Witness`] and collapses it into a vector of [`Range`]s of [`Witnesses`][`Witness`]. +fn collapse_ranges(witnesses: &[Witness]) -> Vec> { + if witnesses.is_empty() { + return Vec::new(); + } + let mut wit = Vec::new(); + let mut last_wit: Witness = witnesses[0]; + + for (i, witness) in witnesses.iter().enumerate() { + if i == 0 { + continue; + }; + let witness_index = witness.witness_index(); + let prev_witness_index = witnesses[i - 1].witness_index(); + if witness_index != prev_witness_index + 1 { + wit.push(last_wit..Witness(prev_witness_index + 1)); + last_wit = *witness; + }; + } + + let last_witness = witnesses.last().unwrap().witness_index(); + wit.push(last_wit..Witness(last_witness + 1)); + + wit +} + +#[cfg(test)] +mod test { + use std::ops::Range; + + use acvm::acir::native_types::Witness; + + use super::collapse_ranges; + + #[test] + fn collapses_single_range() { + let witnesses: Vec<_> = vec![1, 2, 3].into_iter().map(Witness::from).collect(); + + let collapsed_witnesses = collapse_ranges(&witnesses); + + assert_eq!(collapsed_witnesses, vec![Range { start: Witness(1), end: Witness(4) },]) + } + + #[test] + fn collapse_ranges_correctly() { + let witnesses: Vec<_> = + vec![1, 2, 3, 5, 6, 2, 3, 4].into_iter().map(Witness::from).collect(); + + let collapsed_witnesses = collapse_ranges(&witnesses); + + assert_eq!( + collapsed_witnesses, + vec![ + Range { start: Witness(1), end: Witness(4) }, + Range { start: Witness(5), end: Witness(7) }, + Range { start: Witness(2), end: Witness(5) } + ] + ) + } +} diff --git a/compiler/noirc_driver/src/contract.rs b/compiler/noirc_driver/src/contract.rs index da097d4cb86..ae55d239cf3 100644 --- a/compiler/noirc_driver/src/contract.rs +++ b/compiler/noirc_driver/src/contract.rs @@ -5,9 +5,9 @@ use acvm::acir::circuit::Circuit; use fm::FileId; use noirc_abi::{Abi, ContractEvent}; use noirc_errors::debug_info::DebugInfo; +use noirc_evaluator::errors::SsaReport; use super::debug::DebugFile; -use crate::program::{deserialize_circuit, serialize_circuit}; /// Describes the types of smart contract functions that are allowed. /// Unlike the similar enum in noirc_frontend, 'open' and 'unconstrained' @@ -42,6 +42,7 @@ pub struct CompiledContract { pub events: Vec, pub file_map: BTreeMap, + pub warnings: Vec, } /// Each function in the contract will be compiled @@ -60,7 +61,10 @@ pub struct ContractFunction { pub abi: Abi, - #[serde(serialize_with = "serialize_circuit", deserialize_with = "deserialize_circuit")] + #[serde( + serialize_with = "Circuit::serialize_circuit_base64", + deserialize_with = "Circuit::deserialize_circuit_base64" + )] pub bytecode: Circuit, pub debug: DebugInfo, diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index f8908efc596..456c2c49609 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -4,12 +4,12 @@ #![warn(clippy::semicolon_if_nothing_returned)] use clap::Args; -use debug::filter_relevant_files; use fm::FileId; +use iter_extended::vecmap; use noirc_abi::{AbiParameter, AbiType, ContractEvent}; use noirc_errors::{CustomDiagnostic, FileDiagnostic}; +use noirc_evaluator::create_circuit; use noirc_evaluator::errors::RuntimeError; -use noirc_evaluator::{create_circuit, into_abi_params}; use noirc_frontend::graph::{CrateId, CrateName}; use noirc_frontend::hir::def_map::{Contract, CrateDefMap}; use noirc_frontend::hir::Context; @@ -18,10 +18,13 @@ use noirc_frontend::node_interner::FuncId; use serde::{Deserialize, Serialize}; use std::path::Path; +mod abi_gen; mod contract; mod debug; mod program; +use debug::filter_relevant_files; + pub use contract::{CompiledContract, ContractFunction, ContractFunctionType}; pub use debug::DebugFile; pub use program::CompiledProgram; @@ -68,13 +71,6 @@ pub type ErrorsAndWarnings = Vec; /// Helper type for connecting a compilation artifact to the errors or warnings which were produced during compilation. pub type CompilationResult = Result<(T, Warnings), ErrorsAndWarnings>; -// This is here for backwards compatibility -// with the restricted version which only uses one file -pub fn compile_file(context: &mut Context, root_file: &Path) -> CompilationResult { - let crate_id = prepare_crate(context, root_file); - compile_main(context, crate_id, &CompileOptions::default(), None, true) -} - /// 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 { let path_to_std_lib_file = Path::new(STD_CRATE_NAME).join("lib.nr"); @@ -145,12 +141,7 @@ pub fn compute_function_abi( ) -> Option<(Vec, Option)> { let main_function = context.get_main_function(crate_id)?; - let func_meta = context.def_interner.function_meta(&main_function); - - let (parameters, return_type) = func_meta.into_function_signature(); - let parameters = into_abi_params(context, parameters); - let return_type = return_type.map(|typ| AbiType::from_type(context, &typ)); - Some((parameters, return_type)) + Some(abi_gen::compute_function_abi(context, &main_function)) } /// Run the frontend to check the crate for errors then compile the main function if there were none @@ -164,22 +155,24 @@ pub fn compile_main( cached_program: Option, force_compile: bool, ) -> CompilationResult { - let (_, warnings) = check_crate(context, crate_id, options.deny_warnings)?; + let (_, mut warnings) = check_crate(context, crate_id, options.deny_warnings)?; - let main = match context.get_main_function(&crate_id) { - Some(m) => m, - None => { - // TODO(#2155): This error might be a better to exist in Nargo - let err = CustomDiagnostic::from_message( - "cannot compile crate into a program as it does not contain a `main` function", - ) - .in_file(FileId::default()); - return Err(vec![err]); - } - }; + let main = context.get_main_function(&crate_id).ok_or_else(|| { + // TODO(#2155): This error might be a better to exist in Nargo + let err = CustomDiagnostic::from_message( + "cannot compile crate into a program as it does not contain a `main` function", + ) + .in_file(FileId::default()); + vec![err] + })?; let compiled_program = compile_no_check(context, options, main, cached_program, force_compile) .map_err(FileDiagnostic::from)?; + let compilation_warnings = vecmap(compiled_program.warnings.clone(), FileDiagnostic::from); + if options.deny_warnings && !compilation_warnings.is_empty() { + return Err(compilation_warnings); + } + warnings.extend(compilation_warnings); if options.print_acir { println!("Compiled ACIR for main (unoptimized):"); @@ -259,6 +252,7 @@ fn compile_contract_inner( ) -> Result { let mut functions = Vec::new(); let mut errors = Vec::new(); + let mut warnings = Vec::new(); for contract_function in &contract.functions { let function_id = contract_function.function_id; let is_entry_point = contract_function.is_entry_point; @@ -280,6 +274,7 @@ fn compile_contract_inner( continue; } }; + warnings.extend(function.warnings); let modifiers = context.def_interner.function_modifiers(&function_id); let func_type = modifiers .contract_function_type @@ -315,17 +310,16 @@ fn compile_contract_inner( functions, file_map, noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(), + warnings, }) } else { Err(errors) } } -/// Compile the current crate. Assumes self.check_crate is called beforehand! +/// Compile the current crate using `main_function` as the entrypoint. /// -/// This function also assumes all errors in experimental_create_circuit and create_circuit -/// are not warnings. -#[allow(deprecated)] +/// This function assumes [`check_crate`] is called beforehand. pub fn compile_no_check( context: &Context, options: &CompileOptions, @@ -336,20 +330,21 @@ pub fn compile_no_check( let program = monomorphize(main_function, &context.def_interner); let hash = fxhash::hash64(&program); + let hashes_match = cached_program.as_ref().map_or(false, |program| program.hash == hash); // If user has specified that they want to see intermediate steps printed then we should // force compilation even if the program hasn't changed. - if !(force_compile || options.print_acir || options.show_brillig || options.show_ssa) { - if let Some(cached_program) = cached_program { - if hash == cached_program.hash { - return Ok(cached_program); - } - } + let force_compile = + force_compile || options.print_acir || options.show_brillig || options.show_ssa; + + if !force_compile && hashes_match { + return Ok(cached_program.expect("cache must exist for hashes to match")); } - let (circuit, debug, abi) = - create_circuit(context, program, options.show_ssa, options.show_brillig)?; + 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 file_map = filter_relevant_files(&[debug.clone()], &context.file_manager); Ok(CompiledProgram { @@ -359,5 +354,6 @@ pub fn compile_no_check( abi, file_map, noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(), + warnings, }) } diff --git a/compiler/noirc_driver/src/program.rs b/compiler/noirc_driver/src/program.rs index fe991567180..8d509d3bf68 100644 --- a/compiler/noirc_driver/src/program.rs +++ b/compiler/noirc_driver/src/program.rs @@ -3,10 +3,9 @@ use std::collections::BTreeMap; use acvm::acir::circuit::Circuit; use fm::FileId; -use base64::Engine; use noirc_errors::debug_info::DebugInfo; -use serde::{de::Error as DeserializationError, ser::Error as SerializationError}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use noirc_evaluator::errors::SsaReport; +use serde::{Deserialize, Serialize}; use super::debug::DebugFile; @@ -19,31 +18,13 @@ pub struct CompiledProgram { /// Used to short-circuit compilation in the case of the source code not changing since the last compilation. pub hash: u64, - #[serde(serialize_with = "serialize_circuit", deserialize_with = "deserialize_circuit")] + #[serde( + serialize_with = "Circuit::serialize_circuit_base64", + deserialize_with = "Circuit::deserialize_circuit_base64" + )] pub circuit: Circuit, pub abi: noirc_abi::Abi, pub debug: DebugInfo, pub file_map: BTreeMap, -} - -pub(crate) fn serialize_circuit(circuit: &Circuit, s: S) -> Result -where - S: Serializer, -{ - let mut circuit_bytes: Vec = Vec::new(); - circuit.write(&mut circuit_bytes).map_err(S::Error::custom)?; - - let encoded_b64 = base64::engine::general_purpose::STANDARD.encode(circuit_bytes); - s.serialize_str(&encoded_b64) -} - -pub(crate) fn deserialize_circuit<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let bytecode_b64: String = serde::Deserialize::deserialize(deserializer)?; - let circuit_bytes = - base64::engine::general_purpose::STANDARD.decode(bytecode_b64).map_err(D::Error::custom)?; - let circuit = Circuit::read(&*circuit_bytes).map_err(D::Error::custom)?; - Ok(circuit) + pub warnings: Vec, } diff --git a/compiler/noirc_errors/src/debug_info.rs b/compiler/noirc_errors/src/debug_info.rs index 946841c279b..888c24adc1a 100644 --- a/compiler/noirc_errors/src/debug_info.rs +++ b/compiler/noirc_errors/src/debug_info.rs @@ -4,6 +4,7 @@ use acvm::compiler::AcirTransformationMap; use serde_with::serde_as; use serde_with::DisplayFromStr; use std::collections::BTreeMap; +use std::collections::HashMap; use std::mem; use crate::Location; @@ -19,6 +20,14 @@ pub struct DebugInfo { pub locations: BTreeMap>, } +/// Holds OpCodes Counts for Acir and Brillig Opcodes +/// To be printed with `nargo info --profile-info` +#[derive(Default, Debug, Serialize, Deserialize, Clone)] +pub struct OpCodesCount { + pub acir_size: usize, + pub brillig_size: usize, +} + impl DebugInfo { pub fn new(locations: BTreeMap>) -> Self { DebugInfo { locations } @@ -42,4 +51,38 @@ impl DebugInfo { pub fn opcode_location(&self, loc: &OpcodeLocation) -> Option> { self.locations.get(loc).cloned() } + + pub fn count_span_opcodes(&self) -> HashMap { + let mut accumulator: HashMap> = HashMap::new(); + + for (opcode_location, locations) in self.locations.iter() { + for location in locations.iter() { + let opcodes = accumulator.entry(*location).or_insert(Vec::new()); + opcodes.push(opcode_location); + } + } + + let counted_opcodes = accumulator + .iter() + .map(|(location, opcodes)| { + let acir_opcodes: Vec<_> = opcodes + .iter() + .filter(|opcode_location| matches!(opcode_location, OpcodeLocation::Acir(_))) + .collect(); + let brillig_opcodes: Vec<_> = opcodes + .iter() + .filter(|opcode_location| { + matches!(opcode_location, OpcodeLocation::Brillig { .. }) + }) + .collect(); + let opcodes_count = OpCodesCount { + acir_size: acir_opcodes.len(), + brillig_size: brillig_opcodes.len(), + }; + (*location, opcodes_count) + }) + .collect(); + + counted_opcodes + } } diff --git a/compiler/noirc_evaluator/Cargo.toml b/compiler/noirc_evaluator/Cargo.toml index d70c9d3179e..933ec2b300c 100644 --- a/compiler/noirc_evaluator/Cargo.toml +++ b/compiler/noirc_evaluator/Cargo.toml @@ -10,10 +10,10 @@ license.workspace = true [dependencies] noirc_frontend.workspace = true noirc_errors.workspace = true -noirc_abi.workspace = true acvm.workspace = true fxhash.workspace = true iter-extended.workspace = true thiserror.workspace = true num-bigint = "0.4" -im = "15.1" +im = { version = "15.1", features = ["serde"] } +serde.workspace = true 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 4b83d21a702..18fd822b07d 100644 --- a/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -18,6 +18,7 @@ use acvm::brillig_vm::brillig::HeapVector; use acvm::FieldElement; use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use iter_extended::vecmap; +use num_bigint::BigUint; use super::brillig_black_box::convert_black_box_call; use super::brillig_block_variables::BlockVariables; @@ -554,6 +555,25 @@ impl<'block> BrilligBlock<'block> { value_variable, ); } + Instruction::RangeCheck { value, max_bit_size, assert_message } => { + let left = self.convert_ssa_register_value(*value, dfg); + let max = BigUint::from(2_u128).pow(*max_bit_size); + let right = self.brillig_context.allocate_register(); + self.brillig_context.const_instruction( + right, + FieldElement::from_be_bytes_reduce(&max.to_bytes_be()).into(), + ); + + let brillig_binary_op = BrilligBinaryOp::Integer { + op: BinaryIntOp::LessThan, + bit_size: max_bit_size + 1, + }; + let condition = self.brillig_context.allocate_register(); + self.brillig_context.binary_instruction(left, right, condition, brillig_binary_op); + self.brillig_context.constrain_instruction(condition, assert_message.clone()); + self.brillig_context.deallocate_register(condition); + self.brillig_context.deallocate_register(right); + } _ => todo!("ICE: Instruction not supported {instruction:?}"), }; diff --git a/compiler/noirc_evaluator/src/errors.rs b/compiler/noirc_evaluator/src/errors.rs index 58d13c0affd..42672d4d0ad 100644 --- a/compiler/noirc_evaluator/src/errors.rs +++ b/compiler/noirc_evaluator/src/errors.rs @@ -13,6 +13,7 @@ use noirc_errors::{CustomDiagnostic as Diagnostic, FileDiagnostic}; use thiserror::Error; use crate::ssa::ir::{dfg::CallStack, types::NumericType}; +use serde::{Deserialize, Serialize}; #[derive(Debug, PartialEq, Eq, Clone, Error)] pub enum RuntimeError { @@ -53,6 +54,43 @@ fn format_failed_constraint(message: &Option) -> String { } } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum SsaReport { + Warning(InternalWarning), +} + +impl From for FileDiagnostic { + fn from(error: SsaReport) -> FileDiagnostic { + match error { + SsaReport::Warning(warning) => { + let message = warning.to_string(); + let (secondary_message, call_stack) = match warning { + InternalWarning::ReturnConstant { call_stack } => { + ("constant value".to_string(), call_stack) + }, + InternalWarning::VerifyProof { call_stack } => { + ("verify_proof(...) aggregates data for the verifier, the actual verification will be done when the full proof is verified using nargo verify. nargo prove may generate an invalid proof if bad data is used as input to verify_proof".to_string(), call_stack) + }, + }; + let call_stack = vecmap(call_stack, |location| location); + let file_id = call_stack.last().map(|location| location.file).unwrap_or_default(); + let location = call_stack.last().expect("Expected RuntimeError to have a location"); + let diagnostic = + Diagnostic::simple_warning(message, secondary_message, location.span); + diagnostic.in_file(file_id).with_call_stack(call_stack) + } + } + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Error, Serialize, Deserialize)] +pub enum InternalWarning { + #[error("Returning a constant value is not allowed")] + ReturnConstant { call_stack: CallStack }, + #[error("Calling std::verify_proof(...) does not verify a proof")] + VerifyProof { call_stack: CallStack }, +} + #[derive(Debug, PartialEq, Eq, Clone, Error)] pub enum InternalError { #[error("ICE: Both expressions should have degree<=1")] @@ -69,8 +107,6 @@ pub enum InternalError { UndeclaredAcirVar { call_stack: CallStack }, #[error("ICE: Expected {expected:?}, found {found:?}")] UnExpected { expected: String, found: String, call_stack: CallStack }, - #[error("Returning a constant value is not allowed")] - ReturnConstant { call_stack: CallStack }, } impl RuntimeError { @@ -83,8 +119,7 @@ impl RuntimeError { | InternalError::MissingArg { call_stack, .. } | InternalError::NotAConstant { call_stack, .. } | InternalError::UndeclaredAcirVar { call_stack } - | InternalError::UnExpected { call_stack, .. } - | InternalError::ReturnConstant { call_stack, .. }, + | InternalError::UnExpected { call_stack, .. }, ) | RuntimeError::FailedConstraint { call_stack, .. } | RuntimeError::IndexOutOfBounds { call_stack, .. } @@ -111,12 +146,6 @@ impl From for FileDiagnostic { impl RuntimeError { fn into_diagnostic(self) -> Diagnostic { match self { - RuntimeError::InternalError(InternalError::ReturnConstant { ref call_stack }) => { - let message = self.to_string(); - let location = - call_stack.back().expect("Expected RuntimeError to have a location"); - Diagnostic::simple_error(message, "constant value".to_string(), location.span) - } RuntimeError::InternalError(cause) => { Diagnostic::simple_error( "Internal Consistency Evaluators Errors: \n diff --git a/compiler/noirc_evaluator/src/lib.rs b/compiler/noirc_evaluator/src/lib.rs index b5b697e3b65..70751d3e541 100644 --- a/compiler/noirc_evaluator/src/lib.rs +++ b/compiler/noirc_evaluator/src/lib.rs @@ -11,5 +11,4 @@ pub mod ssa; pub mod brillig; -pub use ssa::abi_gen::into_abi_params; pub use ssa::create_circuit; diff --git a/compiler/noirc_evaluator/src/ssa.rs b/compiler/noirc_evaluator/src/ssa.rs index 7cf51a4f0b3..8e1c62edc69 100644 --- a/compiler/noirc_evaluator/src/ssa.rs +++ b/compiler/noirc_evaluator/src/ssa.rs @@ -9,7 +9,10 @@ use std::collections::BTreeSet; -use crate::errors::RuntimeError; +use crate::{ + brillig::Brillig, + errors::{RuntimeError, SsaReport}, +}; use acvm::acir::{ circuit::{Circuit, PublicInputs}, native_types::Witness, @@ -17,13 +20,12 @@ use acvm::acir::{ use noirc_errors::debug_info::DebugInfo; -use noirc_abi::Abi; - -use noirc_frontend::{hir::Context, monomorphization::ast::Program}; +use noirc_frontend::{ + hir_def::function::FunctionSignature, monomorphization::ast::Program, Visibility, +}; -use self::{abi_gen::gen_abi, acir_gen::GeneratedAcir, ssa_gen::Ssa}; +use self::{acir_gen::GeneratedAcir, ssa_gen::Ssa}; -pub mod abi_gen; mod acir_gen; pub(super) mod function_builder; pub mod ir; @@ -39,7 +41,8 @@ pub(crate) fn optimize_into_acir( print_brillig_trace: bool, ) -> Result { let abi_distinctness = program.return_distinctness; - let ssa = SsaBuilder::new(program, print_ssa_passes)? + + let ssa_builder = SsaBuilder::new(program, print_ssa_passes)? .run_pass(Ssa::defunctionalize, "After Defunctionalization:") .run_pass(Ssa::inline_functions, "After Inlining:") // Run mem2reg with the CFG separated into blocks @@ -56,10 +59,17 @@ pub(crate) fn optimize_into_acir( // Run mem2reg once more with the flattened CFG to catch any remaining loads/stores .run_pass(Ssa::mem2reg, "After Mem2Reg:") .run_pass(Ssa::fold_constants, "After Constant Folding:") - .run_pass(Ssa::dead_instruction_elimination, "After Dead Instruction Elimination:") + .run_pass(Ssa::dead_instruction_elimination, "After Dead Instruction Elimination:"); + + let brillig = ssa_builder.to_brillig(print_brillig_trace); + + // Split off any passes the are not necessary for Brillig generation but are necessary for ACIR generation. + // We only need to fill out nested slices as we need to have a known length when dealing with memory operations + // in ACIR gen while this is not necessary in the Brillig IR. + let ssa = ssa_builder + .run_pass(Ssa::fill_internal_slices, "After Fill Internal Slice Dummy Data:") .finish(); - let brillig = ssa.to_brillig(print_brillig_trace); let last_array_uses = ssa.find_last_array_uses(); ssa.into_acir(brillig, abi_distinctness, &last_array_uses) } @@ -67,12 +77,12 @@ pub(crate) fn optimize_into_acir( /// Compiles the [`Program`] into [`ACIR`][acvm::acir::circuit::Circuit]. /// /// The output ACIR is is backend-agnostic and so must go through a transformation pass before usage in proof generation. +#[allow(clippy::type_complexity)] pub fn create_circuit( - context: &Context, program: Program, enable_ssa_logging: bool, enable_brillig_logging: bool, -) -> Result<(Circuit, DebugInfo, Abi), RuntimeError> { +) -> Result<(Circuit, DebugInfo, Vec, Vec, Vec), RuntimeError> { let func_sig = program.main_function_signature.clone(); let mut generated_acir = optimize_into_acir(program, enable_ssa_logging, enable_brillig_logging)?; @@ -83,20 +93,15 @@ pub fn create_circuit( locations, input_witnesses, assert_messages, + warnings, .. } = generated_acir; - let abi = gen_abi(context, func_sig, &input_witnesses, return_witnesses.clone()); - let public_abi = abi.clone().public_abi(); - - let public_parameters = - PublicInputs(public_abi.param_witnesses.values().flatten().copied().collect()); + let (public_parameter_witnesses, private_parameters) = + split_public_and_private_inputs(&func_sig, &input_witnesses); - let all_parameters: BTreeSet = - abi.param_witnesses.values().flatten().copied().collect(); - let private_parameters = all_parameters.difference(&public_parameters.0).copied().collect(); - - let return_values = PublicInputs(return_witnesses.into_iter().collect()); + let public_parameters = PublicInputs(public_parameter_witnesses); + let return_values = PublicInputs(return_witnesses.iter().copied().collect()); let circuit = Circuit { current_witness_index, @@ -119,7 +124,41 @@ pub fn create_circuit( let (optimized_circuit, transformation_map) = acvm::compiler::optimize(circuit); debug_info.update_acir(transformation_map); - Ok((optimized_circuit, debug_info, abi)) + Ok((optimized_circuit, debug_info, input_witnesses, return_witnesses, warnings)) +} + +// Takes each function argument and partitions the circuit's inputs witnesses according to its visibility. +fn split_public_and_private_inputs( + func_sig: &FunctionSignature, + input_witnesses: &[Witness], +) -> (BTreeSet, BTreeSet) { + let mut idx = 0_usize; + if input_witnesses.is_empty() { + return (BTreeSet::new(), BTreeSet::new()); + } + + func_sig + .0 + .iter() + .map(|(_, typ, visibility)| { + let num_field_elements_needed = typ.field_count() as usize; + let witnesses = input_witnesses[idx..idx + num_field_elements_needed].to_vec(); + idx += num_field_elements_needed; + (visibility, witnesses) + }) + .fold((BTreeSet::new(), BTreeSet::new()), |mut acc, (vis, witnesses)| { + // Split witnesses into sets based on their visibility. + if *vis == Visibility::Public { + for witness in witnesses { + acc.0.insert(witness); + } + } else { + for witness in witnesses { + acc.1.insert(witness); + } + } + (acc.0, acc.1) + }) } // This is just a convenience object to bundle the ssa with `print_ssa_passes` for debug printing. @@ -154,6 +193,10 @@ impl SsaBuilder { Ok(self.print(msg)) } + fn to_brillig(&self, print_brillig_trace: bool) -> Brillig { + self.ssa.to_brillig(print_brillig_trace) + } + fn print(self, msg: &str) -> Self { if self.print_ssa_passes { println!("{msg}\n{}", self.ssa); diff --git a/compiler/noirc_evaluator/src/ssa/abi_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/abi_gen/mod.rs deleted file mode 100644 index e4b4026bf21..00000000000 --- a/compiler/noirc_evaluator/src/ssa/abi_gen/mod.rs +++ /dev/null @@ -1,68 +0,0 @@ -use std::collections::BTreeMap; - -use acvm::acir::native_types::Witness; -use iter_extended::{btree_map, vecmap}; -use noirc_abi::{Abi, AbiParameter, AbiType}; -use noirc_frontend::{ - hir::Context, - hir_def::{ - function::{FunctionSignature, Param}, - stmt::HirPattern, - }, - node_interner::NodeInterner, -}; - -/// Attempts to retrieve the name of this parameter. Returns None -/// if this parameter is a tuple or struct pattern. -fn get_param_name<'a>(pattern: &HirPattern, interner: &'a NodeInterner) -> Option<&'a str> { - match pattern { - HirPattern::Identifier(ident) => Some(interner.definition_name(ident.id)), - HirPattern::Mutable(pattern, _) => get_param_name(pattern, interner), - HirPattern::Tuple(_, _) => None, - HirPattern::Struct(_, _, _) => None, - } -} - -pub fn into_abi_params(context: &Context, params: Vec) -> Vec { - vecmap(params, |(pattern, typ, vis)| { - let param_name = get_param_name(&pattern, &context.def_interner) - .expect("Abi for tuple and struct parameters is unimplemented") - .to_owned(); - let as_abi = AbiType::from_type(context, &typ); - AbiParameter { name: param_name, typ: as_abi, visibility: vis.into() } - }) -} - -/// Arranges a function signature and a generated circuit's return witnesses into a -/// `noirc_abi::Abi`. -pub(crate) fn gen_abi( - context: &Context, - func_sig: FunctionSignature, - input_witnesses: &[Witness], - return_witnesses: Vec, -) -> Abi { - let (parameters, return_type) = func_sig; - let parameters = into_abi_params(context, parameters); - let return_type = return_type.map(|typ| AbiType::from_type(context, &typ)); - let param_witnesses = param_witnesses_from_abi_param(¶meters, input_witnesses); - Abi { parameters, return_type, param_witnesses, return_witnesses } -} - -// Takes each abi parameter and shallowly maps to the expected witness range in which the -// parameter's constituent values live. -fn param_witnesses_from_abi_param( - abi_params: &Vec, - input_witnesses: &[Witness], -) -> BTreeMap> { - let mut idx = 0_usize; - - btree_map(abi_params, |param| { - let num_field_elements_needed = param.typ.field_count(); - let mut wit = Vec::new(); - for _ in 0..num_field_elements_needed { - wit.push(input_witnesses[idx]); - idx += 1; - } - (param.name.clone(), wit) - }) -} 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 f54ddd9f4d4..c4b19379ecc 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 @@ -1,7 +1,7 @@ use super::generated_acir::GeneratedAcir; use crate::brillig::brillig_gen::brillig_directive; use crate::brillig::brillig_ir::artifact::GeneratedBrillig; -use crate::errors::{InternalError, RuntimeError}; +use crate::errors::{InternalError, RuntimeError, SsaReport}; use crate::ssa::acir_gen::{AcirDynamicArray, AcirValue}; use crate::ssa::ir::dfg::CallStack; use crate::ssa::ir::types::Type as SsaType; @@ -114,7 +114,7 @@ impl AcirContext { self.acir_ir.current_witness_index() } - pub(crate) fn extract_witness(&self, inputs: &[AcirValue]) -> Vec { + pub(crate) fn extract_witness(&self, inputs: &[AcirValue]) -> Vec { inputs .iter() .flat_map(|value| value.clone().flatten()) @@ -125,7 +125,6 @@ impl AcirContext { .to_expression() .to_witness() .expect("ICE - cannot extract a witness") - .0 }) .collect() } @@ -656,7 +655,11 @@ impl AcirContext { let remainder_var = r_value.into_var()?; // Constrain `q < 2^{max_q_bits}`. - self.range_constrain_var(quotient_var, &NumericType::Unsigned { bit_size: max_q_bits })?; + self.range_constrain_var( + quotient_var, + &NumericType::Unsigned { bit_size: max_q_bits }, + None, + )?; // Constrain `r < 2^{max_rhs_bits}`. // @@ -664,7 +667,11 @@ impl AcirContext { // In the case where `rhs` isn't a power of 2 then this range constraint is required // as the bound constraint creates a new witness. // This opcode will be optimized out if it is redundant so we always add it for safety. - self.range_constrain_var(remainder_var, &NumericType::Unsigned { bit_size: max_rhs_bits })?; + self.range_constrain_var( + remainder_var, + &NumericType::Unsigned { bit_size: max_rhs_bits }, + None, + )?; // Constrain `r < rhs`. self.bound_constraint_with_offset(remainder_var, rhs, predicate, max_rhs_bits)?; @@ -768,12 +775,12 @@ impl AcirContext { let r_var = self.add_constant(r.into()); 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 })?; + self.range_constrain_var(aor, &NumericType::Unsigned { bit_size }, None)?; return Ok(()); } // General case: lhs_offset<=rhs <=> rhs-lhs_offset>=0 <=> rhs-lhs_offset is a 'bits' bit integer let sub_expression = self.sub_var(rhs, lhs_offset)?; //rhs-lhs_offset - self.range_constrain_var(sub_expression, &NumericType::Unsigned { bit_size: bits })?; + self.range_constrain_var(sub_expression, &NumericType::Unsigned { bit_size: bits }, None)?; Ok(()) } @@ -874,6 +881,7 @@ impl AcirContext { &mut self, variable: AcirVar, numeric_type: &NumericType, + message: Option, ) -> Result { match numeric_type { NumericType::Signed { bit_size } | NumericType::Unsigned { bit_size } => { @@ -884,8 +892,15 @@ impl AcirContext { return Ok(variable); } } - let witness = self.var_to_witness(variable)?; + + let witness_var = self.get_or_create_witness_var(variable)?; + let witness = self.var_to_witness(witness_var)?; self.acir_ir.range_constraint(witness, *bit_size)?; + if let Some(message) = message { + self.acir_ir + .assert_messages + .insert(self.acir_ir.last_acir_opcode_location(), message); + } } NumericType::NativeField => { // Range constraining a Field is a no-op @@ -1068,7 +1083,8 @@ impl AcirContext { // Intrinsics only accept Witnesses. This is not a limitation of the // intrinsics, its just how we have defined things. Ideally, we allow // constants too. - let witness = self.var_to_witness(input)?; + let witness_var = self.get_or_create_witness_var(input)?; + let witness = self.var_to_witness(witness_var)?; let num_bits = typ.bit_size(); single_val_witnesses.push(FunctionInput { witness, num_bits }); } @@ -1162,8 +1178,13 @@ impl AcirContext { } /// Terminates the context and takes the resulting `GeneratedAcir` - pub(crate) fn finish(mut self, inputs: Vec) -> GeneratedAcir { - self.acir_ir.input_witnesses = vecmap(inputs, Witness); + pub(crate) fn finish( + mut self, + inputs: Vec, + warnings: Vec, + ) -> GeneratedAcir { + self.acir_ir.input_witnesses = inputs; + self.acir_ir.warnings = warnings; self.acir_ir } diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index e50eb703ade..024bfe4c8ba 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -4,7 +4,7 @@ use std::collections::BTreeMap; use crate::{ brillig::{brillig_gen::brillig_directive, brillig_ir::artifact::GeneratedBrillig}, - errors::{InternalError, RuntimeError}, + errors::{InternalError, RuntimeError, SsaReport}, ssa::ir::dfg::CallStack, }; @@ -53,6 +53,8 @@ pub(crate) struct GeneratedAcir { /// Correspondence between an opcode index and the error message associated with it. pub(crate) assert_messages: BTreeMap, + + pub(crate) warnings: Vec, } impl GeneratedAcir { diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index bbd53a5a204..2f58957c73d 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -3,7 +3,6 @@ mod acir_ir; use std::collections::HashSet; use std::fmt::Debug; -use std::ops::RangeInclusive; use self::acir_ir::acir_variable::{AcirContext, AcirType, AcirVar}; use super::ir::dfg::CallStack; @@ -23,8 +22,11 @@ use super::{ use crate::brillig::brillig_ir::artifact::GeneratedBrillig; use crate::brillig::brillig_ir::BrilligContext; use crate::brillig::{brillig_gen::brillig_fn::FunctionContext as BrilligFunctionContext, Brillig}; -use crate::errors::{InternalError, RuntimeError}; +use crate::errors::{InternalError, InternalWarning, RuntimeError, SsaReport}; pub(crate) use acir_ir::generated_acir::GeneratedAcir; + +use acvm::acir::native_types::Witness; +use acvm::acir::BlackBoxFunc; use acvm::{ acir::{circuit::opcodes::BlockId, native_types::Expression}, FieldElement, @@ -71,9 +73,23 @@ struct Context { /// which utilizes this internal memory for ACIR generation. internal_memory_blocks: HashMap, BlockId>, + /// Maps an internal memory block to its length + /// + /// This is necessary to keep track of an internal memory block's size. + /// We do not need a separate map to keep track of `memory_blocks` as + /// the length is set when we construct a `AcirValue::DynamicArray` and is tracked + /// as part of the `AcirValue` in the `ssa_values` map. + /// The length of an internal memory block is determined before an array operation + /// takes place thus we track it separate here in this map. + internal_mem_block_lengths: HashMap, + /// Number of the next BlockId, it is used to construct /// a new BlockId max_block_id: u32, + + /// 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>, } #[derive(Clone)] @@ -168,7 +184,9 @@ impl Context { initialized_arrays: HashSet::new(), memory_blocks: HashMap::default(), internal_memory_blocks: HashMap::default(), + internal_mem_block_lengths: HashMap::default(), max_block_id: 0, + slice_sizes: HashMap::default(), } } @@ -196,14 +214,19 @@ 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)?; - + let mut warnings = Vec::new(); for instruction_id in entry_block.instructions() { - self.convert_ssa_instruction(*instruction_id, dfg, ssa, &brillig, last_array_uses)?; + warnings.extend(self.convert_ssa_instruction( + *instruction_id, + dfg, + ssa, + &brillig, + last_array_uses, + )?); } - self.convert_ssa_return(entry_block.unwrap_terminator(), dfg)?; - - Ok(self.acir_context.finish(input_witness.collect())) + warnings.extend(self.convert_ssa_return(entry_block.unwrap_terminator(), dfg)?); + Ok(self.acir_context.finish(input_witness, warnings)) } fn convert_brillig_main( @@ -239,8 +262,7 @@ impl Context { for acir_var in output_vars { self.acir_context.return_var(acir_var)?; } - - Ok(self.acir_context.finish(witness_inputs)) + Ok(self.acir_context.finish(witness_inputs, Vec::new())) } /// Adds and binds `AcirVar`s for each numeric block parameter or block parameter array element. @@ -248,7 +270,7 @@ impl Context { &mut self, params: &[ValueId], dfg: &DataFlowGraph, - ) -> Result, RuntimeError> { + ) -> Result, RuntimeError> { // The first witness (if any) is the next one let start_witness = self.acir_context.current_witness_index().0 + 1; for param_id in params { @@ -277,7 +299,8 @@ impl Context { self.ssa_values.insert(*param_id, value); } let end_witness = self.acir_context.current_witness_index().0; - Ok(start_witness..=end_witness) + let witnesses = (start_witness..=end_witness).map(Witness::from).collect(); + Ok(witnesses) } fn convert_ssa_block_param(&mut self, param_type: &Type) -> Result { @@ -347,7 +370,7 @@ impl Context { ) -> Result { let acir_var = self.acir_context.add_variable(); if matches!(numeric_type, NumericType::Signed { .. } | NumericType::Unsigned { .. }) { - self.acir_context.range_constrain_var(acir_var, numeric_type)?; + self.acir_context.range_constrain_var(acir_var, numeric_type, None)?; } Ok(acir_var) } @@ -360,9 +383,10 @@ impl Context { ssa: &Ssa, brillig: &Brillig, last_array_uses: &HashMap, - ) -> Result<(), RuntimeError> { + ) -> Result, RuntimeError> { let instruction = &dfg[instruction_id]; self.acir_context.set_call_stack(dfg.get_call_stack(instruction_id)); + let mut warnings = Vec::new(); match instruction { Instruction::Binary(binary) => { let result_acir_var = self.convert_ssa_binary(binary, dfg)?; @@ -407,7 +431,9 @@ impl Context { let rhs_var = read_from_index(rhs_block_id, i)?; Ok((lhs_var, rhs_var)) }), - _ => unreachable!("ICE: lhs and rhs should be of the same type"), + _ => { + unreachable!("ICE: lhs and rhs should be of the same type") + } } } @@ -463,6 +489,14 @@ impl Context { } } Value::Intrinsic(intrinsic) => { + if matches!( + intrinsic, + Intrinsic::BlackBox(BlackBoxFunc::RecursiveAggregation) + ) { + warnings.push(SsaReport::Warning(InternalWarning::VerifyProof { + call_stack: self.acir_context.get_call_stack(), + })); + } let outputs = self .convert_ssa_intrinsic_call(*intrinsic, arguments, dfg, result_ids)?; @@ -485,7 +519,7 @@ impl Context { self.initialize_array(block_id, len, Some(output.clone()))?; } AcirValue::DynamicArray(_) => { - unreachable!("The output from an intrinsic call is expected to be a single value or an array but got {output:?}"); + // Do nothing as a dynamic array returned from a slice intrinsic should already be initialized } AcirValue::Var(_, _) => { // Do nothing @@ -529,9 +563,17 @@ impl Context { Instruction::Load { .. } => { unreachable!("Expected all load instructions to be removed before acir_gen") } + Instruction::RangeCheck { value, max_bit_size, assert_message } => { + let acir_var = self.convert_numeric_value(*value, dfg)?; + self.acir_context.range_constrain_var( + acir_var, + &NumericType::Unsigned { bit_size: *max_bit_size }, + assert_message.clone(), + )?; + } } self.acir_context.set_call_stack(CallStack::new()); - Ok(()) + Ok(warnings) } fn gen_brillig_for( @@ -616,70 +658,76 @@ impl Context { store_value: Option, ) -> Result { let index_const = dfg.get_numeric_constant(index); - match dfg.type_of_value(array) { - Type::Array(_, _) => { - match self.convert_value(array, dfg) { - AcirValue::Var(acir_var, _) => { - return Err(RuntimeError::InternalError(InternalError::UnExpected { - expected: "an array value".to_string(), - found: format!("{acir_var:?}"), - call_stack: self.acir_context.get_call_stack(), - })) - } - AcirValue::Array(array) => { - if let Some(index_const) = index_const { - let array_size = array.len(); - let index = match index_const.try_to_u64() { - Some(index_const) => index_const as usize, - None => { - let call_stack = self.acir_context.get_call_stack(); - return Err(RuntimeError::TypeConversion { - from: "array index".to_string(), - into: "u64".to_string(), - call_stack, - }); + let value_type = dfg.type_of_value(array); + let (Type::Array(element_types, _) | Type::Slice(element_types)) = &value_type else { + unreachable!("ICE: expected array or slice type"); + + }; + + // TODO(#3188): Need to be able to handle constant index for slices to seriously reduce + // constraint sizes of nested slices + // This can only be done if we accurately flatten nested slices as otherwise we will reach + // index out of bounds errors. If the slice is already flat then we can treat them similarly to arrays. + if matches!(value_type, Type::Slice(_)) + && element_types.iter().any(|element| element.contains_slice_element()) + { + return Ok(false); + } + + match self.convert_value(array, dfg) { + AcirValue::Var(acir_var, _) => { + return Err(RuntimeError::InternalError(InternalError::UnExpected { + expected: "an array value".to_string(), + found: format!("{acir_var:?}"), + call_stack: self.acir_context.get_call_stack(), + })) + } + AcirValue::Array(array) => { + if let Some(index_const) = index_const { + let array_size = array.len(); + let index = match index_const.try_to_u64() { + Some(index_const) => index_const as usize, + None => { + let call_stack = self.acir_context.get_call_stack(); + return Err(RuntimeError::TypeConversion { + from: "array index".to_string(), + into: "u64".to_string(), + call_stack, + }); + } + }; + if self.acir_context.is_constant_one(&self.current_side_effects_enabled_var) { + // Report the error if side effects are enabled. + if index >= array_size { + let call_stack = self.acir_context.get_call_stack(); + return Err(RuntimeError::IndexOutOfBounds { + index, + array_size, + call_stack, + }); + } else { + let value = match store_value { + Some(store_value) => { + let store_value = self.convert_value(store_value, dfg); + AcirValue::Array(array.update(index, store_value)) } + None => array[index].clone(), }; - if self - .acir_context - .is_constant_one(&self.current_side_effects_enabled_var) - { - // Report the error if side effects are enabled. - if index >= array_size { - let call_stack = self.acir_context.get_call_stack(); - return Err(RuntimeError::IndexOutOfBounds { - index, - array_size, - call_stack, - }); - } else { - let value = match store_value { - Some(store_value) => { - let store_value = self.convert_value(store_value, dfg); - AcirValue::Array(array.update(index, store_value)) - } - None => array[index].clone(), - }; - self.define_result(dfg, instruction, value); - return Ok(true); - } - } - // If there is a predicate and the index is not out of range, we can directly perform the read - else if index < array_size && store_value.is_none() { - self.define_result(dfg, instruction, array[index].clone()); - return Ok(true); - } + self.define_result(dfg, instruction, value); + return Ok(true); } } - AcirValue::DynamicArray(_) => (), + // If there is a predicate and the index is not out of range, we can directly perform the read + else if index < array_size && store_value.is_none() { + self.define_result(dfg, instruction, array[index].clone()); + return Ok(true); + } } } - Type::Slice(_) => { - // Do nothing we only want dynamic checks for slices - } - _ => unreachable!("ICE: expected array or slice type"), - } + AcirValue::DynamicArray(_) => (), + }; + Ok(false) } @@ -716,8 +764,24 @@ impl Context { let mut dummy_predicate_index = predicate_index; // We must setup the dummy value to match the type of the value we wish to store - let dummy = - self.array_get_value(&store_type, block_id, &mut dummy_predicate_index)?; + let slice_sizes = if store_type.contains_slice_element() { + self.compute_slice_sizes(store, None, dfg); + self.slice_sizes.get(&store).cloned().ok_or_else(|| { + InternalError::UnExpected { + expected: "Store value should have slice sizes computed".to_owned(), + found: "Missing key in slice sizes map".to_owned(), + call_stack: self.acir_context.get_call_stack(), + } + })? + } else { + vec![] + }; + let dummy = self.array_get_value( + &store_type, + block_id, + &mut dummy_predicate_index, + &slice_sizes, + )?; Some(self.convert_array_set_store_value(&store_value, &dummy)?) } @@ -813,11 +877,31 @@ impl Context { mut var_index: AcirVar, dfg: &DataFlowGraph, ) -> Result { - let (_, _, block_id) = self.check_array_is_initialized(array, dfg)?; + 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]); - let value = self.array_get_value(&res_typ, block_id, &mut var_index)?; + + let value = if !res_typ.contains_slice_element() { + self.array_get_value(&res_typ, block_id, &mut var_index, &[])? + } else { + let slice_sizes = self + .slice_sizes + .get(&array_id) + .expect("ICE: Array with slices should have associated slice sizes"); + + // 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. + let slice_sizes = slice_sizes[1..].to_vec(); + + let value = self.array_get_value(&res_typ, block_id, &mut var_index, &slice_sizes)?; + + // Insert the resulting slice sizes + self.slice_sizes.insert(results[0], slice_sizes); + + value + }; self.define_result(dfg, instruction, value.clone()); @@ -829,6 +913,7 @@ impl Context { ssa_type: &Type, block_id: BlockId, var_index: &mut AcirVar, + slice_sizes: &[usize], ) -> Result { let one = self.acir_context.add_constant(FieldElement::one()); match ssa_type.clone() { @@ -846,20 +931,31 @@ impl Context { let mut values = Vector::new(); for _ in 0..len { for typ in element_types.as_ref() { - values.push_back(self.array_get_value(typ, block_id, var_index)?); + values.push_back(self.array_get_value( + typ, + block_id, + var_index, + slice_sizes, + )?); } } Ok(AcirValue::Array(values)) } - Type::Slice(_) => { - // TODO(#2752): need SSA values here to fetch the len like we do for a Type::Array - // Update this to enable fetching slices from nested arrays - Err(InternalError::UnExpected { - expected: "array".to_owned(), - found: ssa_type.to_string(), - call_stack: self.acir_context.get_call_stack(), + Type::Slice(element_types) => { + // It is not enough to execute this loop and simply pass the size from the parent definition. + // We need the internal sizes of each type in case of a nested slice. + let mut values = Vector::new(); + + let (current_size, new_sizes) = + slice_sizes.split_first().expect("should be able to split"); + + for _ in 0..*current_size { + for typ in element_types.as_ref() { + values + .push_back(self.array_get_value(typ, block_id, var_index, new_sizes)?); + } } - .into()) + Ok(AcirValue::Array(values)) } _ => unreachable!("ICE - expected an array or slice"), } @@ -898,13 +994,10 @@ impl Context { // However, this size is simply the capacity of a slice. The capacity is dependent upon the witness // and may contain data for which we want to restrict access. The true slice length is tracked in a // a separate SSA value and restrictions on slice indices should be generated elsewhere in the SSA. - let array_len = match &array_typ { - Type::Array(_, _) => { - // Flatten the array length to handle arrays of complex types - array_typ.flattened_size() - } - Type::Slice(_) => self.flattened_slice_size(array_id, dfg), - _ => unreachable!("ICE - expected an array"), + let array_len = if !array_typ.contains_slice_element() { + array_typ.flattened_size() + } else { + self.flattened_slice_size(array_id, dfg) }; // Since array_set creates a new array, we create a new block ID for this @@ -926,11 +1019,29 @@ impl Context { self.array_set_value(store_value, result_block_id, &mut var_index)?; - let arr_element_type_sizes = self.internal_block_id(&array_id); + // Set new resulting array to have the same slice sizes as the instruction input + if let Type::Slice(element_types) = &array_typ { + let has_internal_slices = + element_types.as_ref().iter().any(|typ| typ.contains_slice_element()); + if has_internal_slices { + let slice_sizes = self + .slice_sizes + .get(&array_id) + .expect( + "ICE: Expected array with internal slices to have associated slice sizes", + ) + .clone(); + let results = dfg.instruction_results(instruction); + self.slice_sizes.insert(results[0], slice_sizes); + } + } + + let element_type_sizes = + self.init_element_type_sizes_array(&array_typ, array_id, None, dfg)?; let result_value = AcirValue::DynamicArray(AcirDynamicArray { block_id: result_block_id, len: array_len, - element_type_sizes: arr_element_type_sizes, + element_type_sizes, }); self.define_result(dfg, instruction, result_value); Ok(()) @@ -989,7 +1100,7 @@ impl Context { match value { Value::Array { .. } | Value::Instruction { .. } => { let value = self.convert_value(array_id, dfg); - let len = if matches!(array_typ, Type::Array(_, _)) { + let len = if !array_typ.contains_slice_element() { array_typ.flattened_size() } else { self.flattened_slice_size(array_id, dfg) @@ -1013,10 +1124,13 @@ impl Context { &mut self, array_typ: &Type, array_id: ValueId, + array_acir_value: Option, dfg: &DataFlowGraph, ) -> Result { let element_type_sizes = self.internal_block_id(&array_id); // Check whether an internal type sizes array has already been initialized + // Need to look into how to optimize for slices as this could lead to different element type sizes + // for different slices that do not have consistent sizes if self.initialized_arrays.contains(&element_type_sizes) { return Ok(element_type_sizes); } @@ -1024,35 +1138,44 @@ impl Context { let mut flat_elem_type_sizes = Vec::new(); flat_elem_type_sizes.push(0); match array_typ { - Type::Array(element_types, _) => { - for (i, typ) in element_types.as_ref().iter().enumerate() { - flat_elem_type_sizes.push(typ.flattened_size() + flat_elem_type_sizes[i]); - } - } - Type::Slice(element_types) => { + Type::Array(_, _) | Type::Slice(_) => { match &dfg[array_id] { Value::Array { array, .. } => { - for i in 0..element_types.len() { + self.compute_slice_sizes(array_id, None, dfg); + + for (i, value) in array.iter().enumerate() { flat_elem_type_sizes.push( - self.flattened_slice_size(array[i], dfg) + flat_elem_type_sizes[i], + self.flattened_slice_size(*value, dfg) + flat_elem_type_sizes[i], ); } } - Value::Instruction { .. } => { + Value::Instruction { .. } | Value::Param { .. } => { // An instruction representing the slice means it has been processed previously during ACIR gen. // Use the previously defined result of an array operation to fetch the internal type information. - let array_acir_value = self.convert_value(array_id, dfg); + let array_acir_value = if let Some(array_acir_value) = array_acir_value { + array_acir_value + } else { + self.convert_value(array_id, dfg) + }; match array_acir_value { AcirValue::DynamicArray(AcirDynamicArray { 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"), + call_stack: self.acir_context.get_call_stack(), + } + )?; self.copy_dynamic_array( inner_elem_type_sizes, element_type_sizes, - element_types.len() + 1, + 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 { @@ -1063,10 +1186,9 @@ impl Context { } } AcirValue::Array(values) => { - for i in 0..element_types.len() { + for (i, value) in values.iter().enumerate() { flat_elem_type_sizes.push( - Self::flattened_value_size(&values[i]) - + flat_elem_type_sizes[i], + Self::flattened_value_size(value) + flat_elem_type_sizes[i], ); } } @@ -1100,20 +1222,59 @@ impl Context { .into()); } } + // 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)); AcirValue::Var(var, AcirType::field()) }); + let element_type_sizes_len = init_values.len(); self.initialize_array( element_type_sizes, - init_values.len(), + element_type_sizes_len, Some(AcirValue::Array(init_values.into())), )?; + self.internal_mem_block_lengths.insert(element_type_sizes, element_type_sizes_len); + Ok(element_type_sizes) } + fn compute_slice_sizes( + &mut self, + current_array_id: ValueId, + parent_array: Option, + dfg: &DataFlowGraph, + ) { + let (array, typ) = match &dfg[current_array_id] { + Value::Array { array, typ } => (array, typ.clone()), + _ => return, + }; + + if !matches!(typ, Type::Slice(_)) { + return; + } + + let element_size = typ.element_size(); + let true_len = array.len() / element_size; + if let Some(parent_array) = parent_array { + let sizes_list = + self.slice_sizes.get_mut(&parent_array).expect("ICE: expected size list"); + sizes_list.push(true_len); + for value in array { + self.compute_slice_sizes(*value, Some(parent_array), dfg); + } + } else { + // This means the current_array_id is the parent array + // The slice sizes should follow the parent array's type structure + // thus we start our sizes list with the parent array size. + self.slice_sizes.insert(current_array_id, vec![true_len]); + for value in array { + self.compute_slice_sizes(*value, Some(current_array_id), dfg); + } + } + } + fn copy_dynamic_array( &mut self, source: BlockId, @@ -1137,31 +1298,15 @@ impl Context { var_index: AcirVar, dfg: &DataFlowGraph, ) -> Result { - let element_type_sizes = self.init_element_type_sizes_array(array_typ, array_id, dfg)?; - - let element_size = array_typ.element_size(); - - let element_size_var = - self.acir_context.add_constant(FieldElement::from(element_size as u128)); - let outer_offset = self.acir_context.div_var( - var_index, - element_size_var, - AcirType::unsigned(32), - self.current_side_effects_enabled_var, - )?; - let inner_offset_index = self.acir_context.modulo_var( - var_index, - element_size_var, - 32, - self.current_side_effects_enabled_var, - )?; - let inner_offset = - self.acir_context.read_from_memory(element_type_sizes, &inner_offset_index)?; + 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, &element_size_var)?; - let var_index = self.acir_context.mul_var(outer_offset, flat_element_size_var)?; - self.acir_context.add_var(var_index, inner_offset) + self.acir_context.read_from_memory(element_type_sizes, &predicate_index)?; + + Ok(flat_element_size_var) } fn flattened_slice_size(&mut self, array_id: ValueId, dfg: &DataFlowGraph) -> usize { @@ -1181,6 +1326,10 @@ impl Context { let array_acir_value = self.convert_value(array_id, dfg); size += Self::flattened_value_size(&array_acir_value); } + Value::Param { .. } => { + let array_acir_value = self.convert_value(array_id, dfg); + size += Self::flattened_value_size(&array_acir_value); + } _ => { unreachable!("ICE: Unexpected SSA value when computing the slice size"); } @@ -1247,8 +1396,8 @@ impl Context { &mut self, terminator: &TerminatorInstruction, dfg: &DataFlowGraph, - ) -> Result<(), InternalError> { - let (return_values, _call_stack) = match terminator { + ) -> Result, InternalError> { + let (return_values, call_stack) = match terminator { TerminatorInstruction::Return { return_values, call_stack } => { (return_values, call_stack) } @@ -1258,16 +1407,16 @@ impl Context { // The return value may or may not be an array reference. Calling `flatten_value_list` // will expand the array if there is one. let return_acir_vars = self.flatten_value_list(return_values, dfg); + let mut warnings = Vec::new(); for acir_var in return_acir_vars { - // TODO(Guillaume) -- disabled as it has shown to break - // TODO with important programs. We will add it back once - // TODO we change it to a warning. - // if self.acir_context.is_constant(&acir_var) { - // return Err(InternalError::ReturnConstant { call_stack: call_stack.clone() }); - // } + if self.acir_context.is_constant(&acir_var) { + warnings.push(SsaReport::Warning(InternalWarning::ReturnConstant { + call_stack: call_stack.clone(), + })); + } self.acir_context.return_var(acir_var)?; } - Ok(()) + Ok(warnings) } /// Gets the cached `AcirVar` that was converted from the corresponding `ValueId`. If it does @@ -1604,26 +1753,50 @@ impl Context { } Intrinsic::SlicePushBack => { let slice_length = self.convert_value(arguments[0], dfg).into_var()?; + let (array_id, array_typ, _) = + self.check_array_is_initialized(arguments[1], dfg)?; let slice = self.convert_value(arguments[1], dfg); - // TODO(#2461): make sure that we have handled nested struct inputs - let element = self.convert_value(arguments[2], 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)?; + // 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)?; - new_slice.push_back(element); - - Ok(vec![ - AcirValue::Var(new_slice_length, AcirType::field()), - AcirValue::Array(new_slice), - ]) + self.slice_intrinsic_input(&mut new_slice, slice.clone())?; + new_slice.push_back(element.clone()); + + // 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()), + )?; + let mut var_index = slice_length; + self.array_set_value(element, result_block_id, &mut var_index)?; + + 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, + Some(new_slice_val), + dfg, + )?, + }); + Ok(vec![AcirValue::Var(new_slice_length, AcirType::field()), result]) } Intrinsic::SlicePushFront => { let slice_length = self.convert_value(arguments[0], dfg).into_var()?; - let slice = self.convert_value(arguments[1], dfg); - // TODO(#2461): make sure that we have handled nested struct inputs + 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 one = self.acir_context.add_constant(FieldElement::one()); @@ -1645,12 +1818,18 @@ impl Context { 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)?; + 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 mut new_slice = Vector::new(); self.slice_intrinsic_input(&mut new_slice, slice)?; - // TODO(#2461): make sure that we have handled nested struct inputs - let elem = new_slice - .pop_back() - .expect("There are no elements in this slice to be removed"); Ok(vec![ AcirValue::Var(new_slice_length, AcirType::field()), @@ -1667,7 +1846,7 @@ impl Context { let mut new_slice = Vector::new(); self.slice_intrinsic_input(&mut new_slice, slice)?; - // TODO(#2461): make sure that we have handled nested struct inputs + // 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"); @@ -1707,7 +1886,7 @@ impl Context { // 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(#2461): make sure that we have handled nested struct inputs + // TODO(#3364): make sure that we have handled nested struct inputs new_slice.insert(index, element); } @@ -1745,7 +1924,7 @@ impl Context { // 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(#2461): make sure that we have handled nested struct inputs + // TODO(#3364): make sure that we have handled nested struct inputs new_slice.remove(index) } else { // This is a dummy value which should never be used if the appropriate diff --git a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs index 155e5a7baba..058f91adacb 100644 --- a/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/function_builder/mod.rs @@ -1,4 +1,4 @@ -use std::borrow::Cow; +use std::{borrow::Cow, rc::Rc}; use acvm::FieldElement; use noirc_errors::Location; @@ -16,7 +16,8 @@ use super::{ basic_block::BasicBlock, dfg::{CallStack, InsertInstructionResult}, function::RuntimeType, - instruction::{InstructionId, Intrinsic}, + instruction::{Endian, InstructionId, Intrinsic}, + types::NumericType, }, ssa_gen::Ssa, }; @@ -259,9 +260,126 @@ 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() } + /// Insert ssa instructions which computes lhs << rhs by doing lhs*2^rhs + pub(crate) fn insert_shift_left(&mut self, lhs: ValueId, rhs: ValueId) -> ValueId { + let base = self.field_constant(FieldElement::from(2_u128)); + let pow = self.pow(base, rhs); + let typ = self.current_function.dfg.type_of_value(lhs); + let pow = self.insert_cast(pow, typ); + self.insert_binary(lhs, BinaryOp::Mul, pow) + } + + /// Insert ssa instructions which computes lhs << rhs by doing lhs*2^rhs + /// and truncate the result to bit_size + fn insert_wrapping_shift_left( + &mut self, + lhs: ValueId, + rhs: ValueId, + bit_size: u32, + ) -> InsertInstructionResult { + 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 instruction = Instruction::Binary(Binary { lhs, rhs: pow, operator: BinaryOp::Mul }); + if max_bit <= bit_size { + self.insert_instruction(instruction, None) + } else { + let result = self.insert_instruction(instruction, None).first(); + self.insert_instruction( + Instruction::Truncate { value: result, bit_size, max_bit_size: max_bit }, + None, + ) + } + } + + /// Insert ssa instructions which computes lhs >> rhs by doing lhs/2^rhs + pub(crate) fn insert_shift_right(&mut self, lhs: ValueId, rhs: ValueId) -> ValueId { + let base = self.field_constant(FieldElement::from(2_u128)); + let pow = self.pow(base, rhs); + self.insert_binary(lhs, BinaryOp::Div, pow) + } + + /// Computes lhs^rhs via square&multiply, using the bits decomposition of rhs + /// Pseudo-code of the computation: + /// let mut r = 1; + /// let rhs_bits = to_bits(rhs); + /// for i in 1 .. bit_size + 1 { + /// let r_squared = r * r; + /// let b = rhs_bits[bit_size - i]; + /// r = (r_squared * lhs * b) + (1 - b) * r_squared; + /// } + pub(crate) fn pow(&mut self, lhs: ValueId, rhs: ValueId) -> ValueId { + let typ = self.current_function.dfg.type_of_value(rhs); + if let Type::Numeric(NumericType::Unsigned { bit_size }) = typ { + let to_bits = self.import_intrinsic_id(Intrinsic::ToBits(Endian::Little)); + let length = self.field_constant(FieldElement::from(bit_size as i128)); + let result_types = + vec![Type::field(), Type::Array(Rc::new(vec![Type::bool()]), bit_size as usize)]; + let rhs_bits = self.insert_call(to_bits, vec![rhs, length], result_types); + let rhs_bits = rhs_bits[1]; + let one = self.field_constant(FieldElement::one()); + let mut r = one; + for i in 1..bit_size + 1 { + let r_squared = self.insert_binary(r, BinaryOp::Mul, r); + let a = self.insert_binary(r_squared, BinaryOp::Mul, lhs); + let idx = self.field_constant(FieldElement::from((bit_size - i) as i128)); + let b = self.insert_array_get(rhs_bits, idx, Type::field()); + let r1 = self.insert_binary(a, BinaryOp::Mul, b); + let c = self.insert_binary(one, BinaryOp::Sub, b); + let r2 = self.insert_binary(c, BinaryOp::Mul, r_squared); + r = self.insert_binary(r1, BinaryOp::Add, r2); + } + r + } else { + unreachable!("Value must be unsigned in power operation"); + } + } + /// Insert an instruction to extract an element from an array pub(crate) fn insert_array_get( &mut self, diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index badc1e82d50..71e773e3f70 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -46,6 +46,7 @@ pub(crate) enum Intrinsic { BlackBox(BlackBoxFunc), FromField, AsField, + WrappingShiftLeft, } impl std::fmt::Display for Intrinsic { @@ -68,6 +69,7 @@ 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"), } } } @@ -92,7 +94,8 @@ impl Intrinsic { | Intrinsic::ToBits(_) | Intrinsic::ToRadix(_) | Intrinsic::FromField - | Intrinsic::AsField => false, + | Intrinsic::AsField + | Intrinsic::WrappingShiftLeft => false, // Some black box functions have side-effects Intrinsic::BlackBox(func) => matches!(func, BlackBoxFunc::RecursiveAggregation), @@ -119,6 +122,7 @@ 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), } } @@ -150,6 +154,9 @@ pub(crate) enum Instruction { /// Constrains two values to be equal to one another. Constrain(ValueId, ValueId, Option), + /// Range constrain `value` to `max_bit_size` + RangeCheck { value: ValueId, max_bit_size: u32, assert_message: Option }, + /// Performs a function call with a list of its arguments. Call { func: ValueId, arguments: Vec }, @@ -199,7 +206,8 @@ impl Instruction { Instruction::ArraySet { array, .. } => InstructionResultType::Operand(*array), Instruction::Constrain(..) | Instruction::Store { .. } - | Instruction::EnableSideEffects { .. } => InstructionResultType::None, + | Instruction::EnableSideEffects { .. } + | Instruction::RangeCheck { .. } => InstructionResultType::None, Instruction::Load { .. } | Instruction::ArrayGet { .. } | Instruction::Call { .. } => { InstructionResultType::Unknown } @@ -226,9 +234,12 @@ impl Instruction { Truncate { .. } => false, // These either have side-effects or interact with memory - Constrain(..) | EnableSideEffects { .. } | Allocate | Load { .. } | Store { .. } => { - false - } + Constrain(..) + | EnableSideEffects { .. } + | Allocate + | Load { .. } + | Store { .. } + | RangeCheck { .. } => false, Call { func, .. } => match dfg[*func] { Value::Intrinsic(intrinsic) => !intrinsic.has_side_effects(), @@ -259,7 +270,7 @@ impl Instruction { | ArrayGet { .. } | ArraySet { .. } => false, - Constrain(..) | Store { .. } | EnableSideEffects { .. } => true, + Constrain(..) | Store { .. } | EnableSideEffects { .. } | RangeCheck { .. } => true, // Some `Intrinsic`s have side effects so we must check what kind of `Call` this is. Call { func, .. } => match dfg[*func] { @@ -316,6 +327,13 @@ impl Instruction { Instruction::ArraySet { array, index, value } => { Instruction::ArraySet { array: f(*array), index: f(*index), value: f(*value) } } + Instruction::RangeCheck { value, max_bit_size, assert_message } => { + Instruction::RangeCheck { + value: f(*value), + max_bit_size: *max_bit_size, + assert_message: assert_message.clone(), + } + } } } @@ -360,6 +378,9 @@ impl Instruction { Instruction::EnableSideEffects { condition } => { f(*condition); } + Instruction::RangeCheck { value, .. } => { + f(*value); + } } } @@ -457,6 +478,14 @@ impl Instruction { Instruction::Allocate { .. } => None, Instruction::Load { .. } => None, Instruction::Store { .. } => 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 { + return Remove; + } + } + None + } } } } @@ -480,7 +509,11 @@ fn simplify_cast(value: ValueId, dst_typ: &Type, dfg: &mut DataFlowGraph) -> Sim SimplifiedTo(dfg.make_constant(constant, dst_typ.clone())) } ( - Type::Numeric(NumericType::NativeField | NumericType::Unsigned { .. }), + Type::Numeric( + NumericType::NativeField + | NumericType::Unsigned { .. } + | NumericType::Signed { .. }, + ), Type::Numeric(NumericType::Unsigned { bit_size }), ) => { // Field/Unsigned -> unsigned: truncate @@ -814,9 +847,39 @@ fn eval_constant_binary_op( if matches!(operator, BinaryOp::Div | BinaryOp::Mod) && rhs == 0 { return None; } + let result = function(lhs, rhs)?; + // Check for overflow + if result >= 2u128.pow(*bit_size) { + return None; + } + result.into() + } + Type::Numeric(NumericType::Signed { bit_size }) => { + let function = operator.get_i128_function(); - let result = function(lhs, rhs); - truncate(result, *bit_size).into() + let lhs = truncate(lhs.try_into_u128()?, *bit_size); + let rhs = truncate(rhs.try_into_u128()?, *bit_size); + let l_pos = lhs < 2u128.pow(bit_size - 1); + let r_pos = rhs < 2u128.pow(bit_size - 1); + let lhs = if l_pos { lhs as i128 } else { -((2u128.pow(*bit_size) - lhs) as i128) }; + let rhs = if r_pos { rhs as i128 } else { -((2u128.pow(*bit_size) - rhs) as i128) }; + // The divisor is being truncated into the type of the operand, which can potentially + // lead to the rhs being zero. + // If the rhs of a division is zero, attempting to evaluate the division will cause a compiler panic. + // Thus, we do not evaluate the division in this method, as we want to avoid triggering a panic, + // and the operation should be handled by ACIR generation. + if matches!(operator, BinaryOp::Div | BinaryOp::Mod) && rhs == 0 { + return None; + } + + let result = function(lhs, rhs)?; + // Check for overflow + if result >= 2i128.pow(*bit_size - 1) || result < -(2i128.pow(*bit_size - 1)) { + return None; + } + let result = + if result >= 0 { result as u128 } else { (2i128.pow(*bit_size) + result) as u128 }; + result.into() } _ => return None, }; @@ -850,18 +913,33 @@ impl BinaryOp { } } - fn get_u128_function(self) -> fn(u128, u128) -> u128 { + fn get_u128_function(self) -> fn(u128, u128) -> Option { + match self { + BinaryOp::Add => u128::checked_add, + BinaryOp::Sub => u128::checked_sub, + BinaryOp::Mul => u128::checked_mul, + BinaryOp::Div => u128::checked_div, + BinaryOp::Mod => u128::checked_rem, + BinaryOp::And => |x, y| Some(x & y), + BinaryOp::Or => |x, y| Some(x | y), + BinaryOp::Xor => |x, y| Some(x ^ y), + BinaryOp::Eq => |x, y| Some((x == y) as u128), + BinaryOp::Lt => |x, y| Some((x < y) as u128), + } + } + + fn get_i128_function(self) -> fn(i128, i128) -> Option { match self { - BinaryOp::Add => u128::wrapping_add, - BinaryOp::Sub => u128::wrapping_sub, - BinaryOp::Mul => u128::wrapping_mul, - BinaryOp::Div => u128::wrapping_div, - BinaryOp::Mod => u128::wrapping_rem, - BinaryOp::And => |x, y| x & y, - BinaryOp::Or => |x, y| x | y, - BinaryOp::Xor => |x, y| x ^ y, - BinaryOp::Eq => |x, y| (x == y) as u128, - BinaryOp::Lt => |x, y| (x < y) as u128, + BinaryOp::Add => i128::checked_add, + BinaryOp::Sub => i128::checked_sub, + BinaryOp::Mul => i128::checked_mul, + BinaryOp::Div => i128::checked_div, + BinaryOp::Mod => i128::checked_rem, + BinaryOp::And => |x, y| Some(x & y), + BinaryOp::Or => |x, y| Some(x | y), + BinaryOp::Xor => |x, y| Some(x ^ y), + BinaryOp::Eq => |x, y| Some((x == y) as i128), + BinaryOp::Lt => |x, y| Some((x < y) as i128), } } } diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs index 956c7077b87..f86a9245ca6 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs @@ -245,6 +245,9 @@ 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 aee8e456b13..c6b1f3c7528 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/printer.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/printer.rs @@ -172,5 +172,8 @@ pub(crate) fn display_instruction( 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 e69e936372d..7fe0713e748 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/types.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/types.rs @@ -79,6 +79,18 @@ impl Type { } } + pub(crate) fn contains_slice_element(&self) -> bool { + match self { + Type::Array(elements, _) => { + elements.iter().any(|element| element.contains_slice_element()) + } + Type::Slice(_) => true, + Type::Numeric(_) => 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; diff --git a/compiler/noirc_evaluator/src/ssa/opt/fill_internal_slices.rs b/compiler/noirc_evaluator/src/ssa/opt/fill_internal_slices.rs new file mode 100644 index 00000000000..d12b01b9196 --- /dev/null +++ b/compiler/noirc_evaluator/src/ssa/opt/fill_internal_slices.rs @@ -0,0 +1,693 @@ +//! This module defines the internal slices data fill pass. +//! The purpose of this pass is to fill out nested slice values represented by SSA array values. +//! "Filling out" a nested slice specifically refers to making a nested slice's internal slice types +//! match up in their size. This pass is necessary for dynamic array operations to work in ACIR gen +//! as we need to have a known size for any memory operations. As slice types do not carry a size we +//! need to make sure all nested internal slices have the same size in order to accurately +//! read from or write to a nested slice. This pass ultimately attaches dummy data to any smaller internal slice types. +//! +//! A simple example: +//! If we have a slice of the type [[Field]] which is of length 2. The internal slices themselves +//! could be of different sizes, such as 3 and 4. An array operation on this nested slice would look +//! something like below: +//! array_get [Field 3, [Field 1, Field 1, Field 1], Field 4, [Field 2, Field 2, Field 2, Field 2]], index Field v0 +//! Will get translated into a new instruction like such: +//! array_get [Field 3, [Field 1, Field 1, Field 1, Field 0], Field 4, [Field 2, Field 2, Field 2, Field 2]], index Field v0 +//! +//! +//! TODO(#3188): Currently the pass only works on a single flattened block. This should be updated in followup work. +//! The steps of the pass are as follows: +//! - Process each instruction of the block to collect relevant slice size information. We want to find the maximum size that a nested slice +//! potentially could be. Slices can potentially be set to larger array values or used in intrinsics that increase or shorten their size. +//! - Track all array constants and compute an initial map of their nested slice sizes. The slice sizes map is simply a map of an SSA array value +//! to its array size and then any child slice values that may exist. +//! - We also track a map to resolve a starting array constant to its final possible array value. This map is updated on the appropriate instructions +//! such as ArraySet or any slice intrinsics. +//! - On an ArrayGet operation add the resulting value as a possible child of the original slice. In SSA we will reuse the same memory block +//! for the nested slice and must account for an internal slice being fetched and set to a larger value, otherwise we may have an out of bounds error. +//! Also set the resulting fetched value to have the same internal slice size map as the children of the original array used in the operation. +//! - On an ArraySet operation we set the resulting value to have the same slice sizes map as the original array used in the operation. Like the result of +//! an ArrayGet we need to also add the `value` for an ArraySet as a possible child slice of the original array. +//! - For slice intrinsics we set the resulting value to have the same slice sizes map as the original array the same way as we do in an ArraySet. +//! However, with a slice intrinsic we also increase the size for the respective slice intrinsics. +//! 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 size, +//! not fill in the appropriate dummies and then get an out of bounds error later when executing the ACIR. We always want to compute +//! what a slice maximum size could be. +//! - Now we need to add each instruction back except with the updated original array values. +//! - Resolve the original slice value to what its final value would be using the previously computed map. +//! - Find the max size as each layer of the recursive nested slice type. +//! For instance in the example above we have a slice of depth 2 with the max sizes of [2, 4]. +//! - Follow the slice type to check whether the SSA value is under the specified max size. If a slice value +//! is under the max size we then attach dummy data. +//! - Construct a final nested slice with the now attached dummy data and replace the original array in the previously +//! saved ArrayGet and ArraySet instructions. + +use crate::ssa::{ + ir::{ + basic_block::BasicBlockId, + dfg::CallStack, + function::Function, + function_inserter::FunctionInserter, + instruction::{Instruction, InstructionId, Intrinsic}, + post_order::PostOrder, + types::Type, + value::{Value, ValueId}, + }, + ssa_gen::Ssa, +}; + +use acvm::FieldElement; +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(); + } + self + } +} + +struct Context<'f> { + post_order: PostOrder, + inserter: FunctionInserter<'f>, + + /// Maps SSA array values representing a slice's contents to its updated array value + /// after an array set or a slice intrinsic operation. + /// Maps original value -> result + mapped_slice_values: HashMap, + + /// Maps an updated array value following an array operation to its previous value. + /// When used in conjunction with `mapped_slice_values` we form a two way map of all array + /// values being used in array operations. + /// Maps result -> original value + slice_parents: HashMap, +} + +impl<'f> Context<'f> { + fn new(function: &'f mut Function) -> Self { + let post_order = PostOrder::with_function(function); + let inserter = FunctionInserter::new(function); + + Context { + post_order, + inserter, + mapped_slice_values: HashMap::default(), + slice_parents: HashMap::default(), + } + } + + fn process_blocks(&mut self) { + let mut block_order = PostOrder::with_function(self.inserter.function).into_vec(); + block_order.reverse(); + for block in block_order { + self.process_block(block); + } + } + + fn process_block(&mut self, block: BasicBlockId) { + // Fetch SSA values potentially with internal slices + let instructions = self.inserter.function.dfg[block].take_instructions(); + + // Values containing nested slices to be replaced + let mut slice_values = Vec::new(); + // Maps SSA array ID representing slice contents to its length and a list of its potential internal slices + // This map is constructed once for an array constant and is then updated + // according to the rules in `collect_slice_information`. + let mut slice_sizes: HashMap)> = HashMap::default(); + + // Update the slice sizes map to help find the potential max size of each nested slice. + for instruction in instructions.iter() { + self.collect_slice_information(*instruction, &mut slice_values, &mut slice_sizes); + } + + // Add back every instruction with the updated nested slices. + for instruction in instructions { + self.push_updated_instruction(instruction, &slice_values, &slice_sizes, block); + } + + self.inserter.map_terminator_in_place(block); + } + + /// Determine how the slice sizes map needs to be updated according to the provided instruction. + fn collect_slice_information( + &mut self, + instruction: InstructionId, + slice_values: &mut Vec, + slice_sizes: &mut HashMap)>, + ) { + let results = self.inserter.function.dfg.instruction_results(instruction); + match &self.inserter.function.dfg[instruction] { + Instruction::ArrayGet { array, .. } => { + let array_typ = self.inserter.function.dfg.type_of_value(*array); + let array_value = &self.inserter.function.dfg[*array]; + // If we have an SSA value containing nested slices we should mark it + // as a slice that potentially requires to be filled with dummy data. + if matches!(array_value, Value::Array { .. }) && array_typ.contains_slice_element() + { + slice_values.push(*array); + // Initial insertion into the slice sizes map + // Any other insertions should only occur if the value is already + // a part of the map. + self.compute_slice_sizes(*array, slice_sizes); + } + + let res_typ = self.inserter.function.dfg.type_of_value(results[0]); + if res_typ.contains_slice_element() { + if let Some(inner_sizes) = slice_sizes.get_mut(array) { + // Include the result in the parent array potential children + // If the result has internal slices and is called in an array set + // we could potentially have a new larger slice which we need to account for + inner_sizes.1.push(results[0]); + self.slice_parents.insert(results[0], *array); + + let inner_sizes_iter = inner_sizes.1.clone(); + for slice_value in inner_sizes_iter { + let inner_slice = slice_sizes.get(&slice_value).unwrap_or_else(|| { + panic!("ICE: should have inner slice set for {slice_value}") + }); + slice_sizes.insert(results[0], inner_slice.clone()); + } + } + } + } + Instruction::ArraySet { array, value, .. } => { + let array_typ = self.inserter.function.dfg.type_of_value(*array); + let array_value = &self.inserter.function.dfg[*array]; + // If we have an SSA value containing nested slices we should mark it + // as a slice that potentially requires to be filled with dummy data. + if matches!(array_value, Value::Array { .. }) && array_typ.contains_slice_element() + { + slice_values.push(*array); + // Initial insertion into the slice sizes map + // Any other insertions should only occur if the value is already + // a part of the map. + self.compute_slice_sizes(*array, slice_sizes); + } + + let value_typ = self.inserter.function.dfg.type_of_value(*value); + if value_typ.contains_slice_element() { + self.compute_slice_sizes(*value, slice_sizes); + + 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]); + self.slice_parents.insert(results[0], *array); + } + } + Instruction::Call { func, arguments } => { + let func = &self.inserter.function.dfg[*func]; + if let Value::Intrinsic(intrinsic) = func { + let (argument_index, result_index) = match intrinsic { + Intrinsic::SlicePushBack + | Intrinsic::SlicePushFront + | Intrinsic::SlicePopBack + | Intrinsic::SliceInsert + | Intrinsic::SliceRemove => (1, 1), + Intrinsic::SlicePopFront => (1, 2), + _ => return, + }; + match intrinsic { + Intrinsic::SlicePushBack + | Intrinsic::SlicePushFront + | Intrinsic::SliceInsert => { + let slice_contents = arguments[argument_index]; + if let Some(inner_sizes) = slice_sizes.get_mut(&slice_contents) { + inner_sizes.0 += 1; + + let inner_sizes = inner_sizes.clone(); + slice_sizes.insert(results[result_index], inner_sizes); + + self.mapped_slice_values + .insert(slice_contents, results[result_index]); + } + } + Intrinsic::SlicePopBack + | Intrinsic::SlicePopFront + | Intrinsic::SliceRemove => { + let slice_contents = arguments[argument_index]; + // 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*** + if let Some(inner_sizes) = slice_sizes.get(&slice_contents) { + let inner_sizes = inner_sizes.clone(); + slice_sizes.insert(results[result_index], inner_sizes); + + self.mapped_slice_values + .insert(slice_contents, results[result_index]); + } + } + _ => {} + } + } + } + _ => {} + } + } + + fn push_updated_instruction( + &mut self, + instruction: InstructionId, + slice_values: &[ValueId], + slice_sizes: &HashMap)>, + block: BasicBlockId, + ) { + match &self.inserter.function.dfg[instruction] { + Instruction::ArrayGet { array, .. } | Instruction::ArraySet { array, .. } => { + 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, + block, + call_stack, + ); + } else { + self.inserter.push_instruction(instruction, block); + } + } + _ => { + self.inserter.push_instruction(instruction, block); + } + } + } + + /// Construct an updated ArrayGet or ArraySet instruction where the array value + /// has been replaced by a newly filled in array according to the max internal + /// slice sizes. + fn get_updated_array_op_instr( + &mut self, + array_id: ValueId, + slice_sizes: &HashMap)>, + instruction: InstructionId, + ) -> (Instruction, CallStack) { + let mapped_slice_value = self.resolve_slice_value(array_id); + + let (current_size, _) = slice_sizes + .get(&mapped_slice_value) + .unwrap_or_else(|| panic!("should have slice sizes: {mapped_slice_value}")); + + let mut max_sizes = Vec::new(); + + 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); + + let new_array = self.attach_slice_dummies(&typ, Some(array_id), true, &max_sizes); + + let instruction_id = instruction; + let (instruction, call_stack) = self.inserter.map_instruction(instruction_id); + let new_array_op_instr = match instruction { + Instruction::ArrayGet { index, .. } => { + Instruction::ArrayGet { array: new_array, index } + } + Instruction::ArraySet { index, value, .. } => { + Instruction::ArraySet { array: new_array, index, value } + } + _ => panic!("Expected array set"), + }; + + (new_array_op_instr, call_stack) + } + + fn attach_slice_dummies( + &mut self, + typ: &Type, + value: Option, + is_parent_slice: bool, + max_sizes: &[usize], + ) -> ValueId { + match typ { + Type::Numeric(_) => { + if let Some(value) = value { + self.inserter.resolve(value) + } else { + let zero = FieldElement::zero(); + self.inserter.function.dfg.make_constant(zero, Type::field()) + } + } + Type::Array(element_types, len) => { + if let Some(value) = value { + self.inserter.resolve(value) + } else { + let mut array = im::Vector::new(); + for _ in 0..*len { + for typ in element_types.iter() { + array.push_back(self.attach_slice_dummies(typ, None, false, max_sizes)); + } + } + self.inserter.function.dfg.make_array(array, typ.clone()) + } + } + Type::Slice(element_types) => { + let (current_size, max_sizes) = + max_sizes.split_first().expect("ICE: Missing internal slice max size"); + let mut max_size = *current_size; + if let Some(value) = value { + let mut slice = im::Vector::new(); + + let array = match self.inserter.function.dfg[value].clone() { + Value::Array { array, .. } => array, + _ => panic!("Expected an array value"), + }; + + if is_parent_slice { + max_size = array.len() / element_types.len(); + } + for i in 0..max_size { + for (element_index, element_type) in element_types.iter().enumerate() { + let index_usize = i * element_types.len() + element_index; + let valid_index = index_usize < array.len(); + let maybe_value = + if valid_index { Some(array[index_usize]) } else { None }; + slice.push_back(self.attach_slice_dummies( + element_type, + maybe_value, + false, + max_sizes, + )); + } + } + + self.inserter.function.dfg.make_array(slice, typ.clone()) + } else { + let mut slice = im::Vector::new(); + for _ in 0..max_size { + for typ in element_types.iter() { + slice.push_back(self.attach_slice_dummies(typ, None, false, max_sizes)); + } + } + self.inserter.function.dfg.make_array(slice, typ.clone()) + } + } + Type::Reference => { + unreachable!("ICE: Generating dummy data for references is unsupported") + } + Type::Function => { + unreachable!("ICE: Generating dummy data for functions is unsupported") + } + } + } + + // This methods computes a map representing a nested slice. + // The method also automatically computes the given max slice size + // at each depth of the recursive type. + // For example if we had a next slice + fn compute_slice_sizes( + &self, + array_id: ValueId, + slice_sizes: &mut HashMap)>, + ) { + if let Value::Array { array, typ } = &self.inserter.function.dfg[array_id].clone() { + if let Type::Slice(_) = typ { + let element_size = typ.element_size(); + let len = array.len() / element_size; + let mut slice_value = (len, vec![]); + for value in array { + let typ = self.inserter.function.dfg.type_of_value(*value); + if let Type::Slice(_) = typ { + slice_value.1.push(*value); + self.compute_slice_sizes(*value, slice_sizes); + } + } + // Mark the correct max size based upon an array values internal structure + let mut max_size = 0; + for inner_value in slice_value.1.iter() { + let inner_slice = + slice_sizes.get(inner_value).expect("ICE: should have inner slice set"); + if inner_slice.0 > max_size { + max_size = inner_slice.0; + } + } + for inner_value in slice_value.1.iter() { + let inner_slice = + slice_sizes.get_mut(inner_value).expect("ICE: should have inner slice set"); + if inner_slice.0 < max_size { + inner_slice.0 = max_size; + } + } + slice_sizes.insert(array_id, slice_value); + } + } + } + + /// Determine the maximum possible size of an internal slice at each + /// layer of a nested slice. + /// + /// If the slice map is incorrectly formed the function will exceed + /// the type's nested slice depth and panic. + fn compute_slice_max_sizes( + &self, + array_id: ValueId, + slice_sizes: &HashMap)>, + max_sizes: &mut Vec, + depth: usize, + ) { + let array_id = self.resolve_slice_value(array_id); + let (current_size, inner_slices) = slice_sizes + .get(&array_id) + .unwrap_or_else(|| panic!("should have slice sizes: {array_id}")); + + if inner_slices.is_empty() { + return; + } + + let mut max = *current_size; + for inner_slice in inner_slices.iter() { + let inner_slice = &self.resolve_slice_value(*inner_slice); + + let (inner_size, _) = slice_sizes[inner_slice]; + if inner_size > max { + max = inner_size; + } + 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; + } + } + + /// Compute the depth of nested slices in a given Type. + /// The depth follows the recursive type structure of a slice. + fn compute_nested_slice_depth(typ: &Type) -> usize { + let mut depth = 0; + if let Type::Slice(element_types) = typ { + depth += 1; + for typ in element_types.as_ref() { + depth += Self::compute_nested_slice_depth(typ); + } + } + depth + } + + /// Resolves a ValueId representing a slice's contents to its updated value. + /// If there is no resolved value for the supplied value, the value which + /// was passed to the method is returned. + fn resolve_slice_value(&self, array_id: ValueId) -> ValueId { + match self.mapped_slice_values.get(&array_id) { + Some(value) => self.resolve_slice_value(*value), + None => array_id, + } + } + + /// Resolves a ValueId representing a slice's contents to its previous value. + /// If there is no resolved parent value it means we have the original slice value + /// and the value which was passed to the method is returned. + fn resolve_slice_parent(&self, array_id: ValueId) -> ValueId { + match self.slice_parents.get(&array_id) { + Some(value) => self.resolve_slice_parent(*value), + None => array_id, + } + } +} + +#[cfg(test)] +mod tests { + + use std::rc::Rc; + + use acvm::FieldElement; + use im::vector; + + use crate::ssa::{ + function_builder::FunctionBuilder, + ir::{ + dfg::DataFlowGraph, + function::RuntimeType, + instruction::{BinaryOp, Instruction}, + map::Id, + types::Type, + value::ValueId, + }, + }; + + #[test] + fn test_simple_nested_slice() { + // We want to test that a nested slice with two internal slices of primitive types + // fills the smaller internal slice with dummy data to match the length of the + // larger internal slice. + + // Note that slices are a represented by a tuple of (length, contents). + // The type of the nested slice in this test is [[Field]]. + // + // This is the original SSA: + // acir fn main f0 { + // b0(v0: Field): + // v2 = lt v0, Field 2 + // constrain v2 == Field 1 'Index out of bounds' + // v11 = array_get [[Field 3, [Field 1, Field 1, Field 1]], [Field 4, [Field 2, Field 2, Field 2, Field 2]]], index Field v0 + // constrain v11 == Field 4 + // return + // } + + let main_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), main_id, RuntimeType::Acir); + + let main_v0 = builder.add_parameter(Type::field()); + + let two = builder.field_constant(2_u128); + // Every slice access checks against the dynamic slice length + let slice_access_check = builder.insert_binary(main_v0, BinaryOp::Lt, two); + let one = builder.field_constant(1_u128); + builder.insert_constrain(slice_access_check, one, Some("Index out of bounds".to_owned())); + + let field_element_type = Rc::new(vec![Type::field()]); + let inner_slice_contents_type = Type::Slice(field_element_type); + + let inner_slice_small_len = builder.field_constant(3_u128); + let inner_slice_small_contents = + builder.array_constant(vector![one, one, one], inner_slice_contents_type.clone()); + + let inner_slice_big_len = builder.field_constant(4_u128); + let inner_slice_big_contents = + builder.array_constant(vector![two, two, two, two], inner_slice_contents_type.clone()); + + let outer_slice_element_type = Rc::new(vec![Type::field(), inner_slice_contents_type]); + let outer_slice_type = Type::Slice(outer_slice_element_type); + + let outer_slice_contents = builder.array_constant( + vector![ + inner_slice_small_len, + inner_slice_small_contents, + inner_slice_big_len, + inner_slice_big_contents + ], + outer_slice_type, + ); + // Fetching the length of the second nested slice + // We must use a parameter to main as we do not want the array operation to be simplified out during SSA gen. The filling of internal slices + // is necessary for dynamic nested slices and thus we want to generate the SSA that ACIR gen would be converting. + let array_get_res = builder.insert_array_get(outer_slice_contents, main_v0, Type::field()); + + let four = builder.field_constant(4_u128); + builder.insert_constrain(array_get_res, four, None); + builder.terminate_with_return(vec![]); + + // Note that now the smaller internal slice should have extra dummy data that matches the larger internal slice's size. + // + // Expected SSA: + // acir fn main f0 { + // b0(v0: Field): + // v10 = lt v0, Field 2 + // constrain v10 == Field 1 'Index out of bounds' + // v18 = array_get [Field 3, [Field 1, Field 1, Field 1, Field 0], Field 4, [Field 2, Field 2, Field 2, Field 2]], index v0 + // constrain v18 == Field 4 + // return + // } + + let ssa = builder.finish().fill_internal_slices(); + + let func = ssa.main(); + let block_id = func.entry_block(); + + // Check the array get expression has replaced its nested slice with a new slice + // where the internal slice has dummy data attached to it. + let instructions = func.dfg[block_id].instructions(); + let array_id = instructions + .iter() + .find_map(|instruction| { + if let Instruction::ArrayGet { array, .. } = func.dfg[*instruction] { + Some(array) + } else { + None + } + }) + .expect("Should find array_get instruction"); + + let (array_constant, _) = + func.dfg.get_array_constant(array_id).expect("should have an array constant"); + + let inner_slice_small_len = func + .dfg + .get_numeric_constant(array_constant[0]) + .expect("should have a numeric constant"); + assert_eq!( + inner_slice_small_len, + FieldElement::from(3u128), + "The length of the smaller internal slice should be unchanged" + ); + + let (inner_slice_small_contents, _) = + func.dfg.get_array_constant(array_constant[1]).expect("should have an array constant"); + let small_capacity = inner_slice_small_contents.len(); + assert_eq!(small_capacity, 4, "The inner slice contents should contain dummy element"); + + compare_array_constants(&inner_slice_small_contents, &[1, 1, 1, 0], &func.dfg); + + let inner_slice_big_len = func + .dfg + .get_numeric_constant(array_constant[2]) + .expect("should have a numeric constant"); + assert_eq!( + inner_slice_big_len, + FieldElement::from(4u128), + "The length of the larger internal slice should be unchanged" + ); + + let (inner_slice_big_contents, _) = + func.dfg.get_array_constant(array_constant[3]).expect("should have an array constant"); + let big_capacity = inner_slice_big_contents.len(); + assert_eq!( + small_capacity, big_capacity, + "The length of both internal slice contents should be the same" + ); + + compare_array_constants(&inner_slice_big_contents, &[2u128; 4], &func.dfg); + } + + fn compare_array_constants( + got_list: &im::Vector, + expected_list: &[u128], + dfg: &DataFlowGraph, + ) { + for i in 0..got_list.len() { + let got_value = + dfg.get_numeric_constant(got_list[i]).expect("should have a numeric constant"); + assert_eq!( + got_value, + FieldElement::from(expected_list[i]), + "Value is different than expected" + ); + } + } +} diff --git a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index f35e8023584..d2ed21c60d7 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -662,6 +662,22 @@ impl<'f> Context<'f> { self.remember_store(address, value); Instruction::Store { address, value } } + Instruction::RangeCheck { value, max_bit_size, assert_message } => { + // Replace value with `value * predicate` to zero out value when predicate is inactive. + + // Condition needs to be cast to argument type in order to multiply them together. + let argument_type = self.inserter.function.dfg.type_of_value(value); + let casted_condition = self.insert_instruction( + Instruction::Cast(condition, argument_type), + call_stack.clone(), + ); + + let value = self.insert_instruction( + Instruction::binary(BinaryOp::Mul, value, casted_condition), + call_stack.clone(), + ); + Instruction::RangeCheck { value, max_bit_size, assert_message } + } other => other, } } else { 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 3041dddd573..32979f78632 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 @@ -194,7 +194,8 @@ impl<'a> ValueMerger<'a> { for i in 0..len { for (element_index, element_type) in element_types.iter().enumerate() { - let index_value = ((i * element_types.len() + element_index) as u128).into(); + let index_usize = i * element_types.len() + element_index; + let index_value = (index_usize as u128).into(); let index = self.dfg.make_constant(index_value, Type::field()); let typevars = Some(vec![element_type.clone()]); @@ -202,7 +203,7 @@ impl<'a> ValueMerger<'a> { let mut get_element = |array, typevars, len| { // The smaller slice is filled with placeholder data. Codegen for slice accesses must // include checks against the dynamic slice length so that this placeholder data is not incorrectly accessed. - if len <= index_value.to_u128() as usize { + if len <= index_usize { self.make_slice_dummy_data(element_type) } else { let get = Instruction::ArrayGet { array, index }; @@ -239,6 +240,11 @@ impl<'a> ValueMerger<'a> { Value::Instruction { instruction: instruction_id, .. } => { let instruction = &self.dfg[*instruction_id]; match instruction { + // TODO(#3188): A slice can be the result of an ArrayGet when it is the + // fetched from a slice of slices or as a struct field. + // However, we need to incorporate nested slice support in flattening + // in order for this to be valid + // Instruction::ArrayGet { array, .. } => {} Instruction::ArraySet { array, .. } => { let array = *array; let len = self.get_slice_length(array); @@ -323,7 +329,9 @@ impl<'a> ValueMerger<'a> { self.dfg.make_array(array, typ.clone()) } Type::Slice(_) => { - unreachable!("ICE: Slices of slice is unsupported") + // TODO(#3188): Need to update flattening to use true user facing length of slices + // to accurately construct dummy data + unreachable!("ICE: Cannot return a slice of slices from an if expression") } Type::Reference => { unreachable!("ICE: Merging references is unsupported") diff --git a/compiler/noirc_evaluator/src/ssa/opt/mod.rs b/compiler/noirc_evaluator/src/ssa/opt/mod.rs index 4d003c0594b..95784194d28 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/mod.rs @@ -8,6 +8,7 @@ mod assert_constant; mod constant_folding; mod defunctionalize; mod die; +mod fill_internal_slices; pub(crate) mod flatten_cfg; mod inlining; mod mem2reg; diff --git a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs index 26c818250dc..4879facd780 100644 --- a/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs +++ b/compiler/noirc_evaluator/src/ssa/ssa_gen/context.rs @@ -13,7 +13,8 @@ use crate::ssa::function_builder::FunctionBuilder; use crate::ssa::ir::dfg::DataFlowGraph; use crate::ssa::ir::function::FunctionId as IrFunctionId; use crate::ssa::ir::function::{Function, RuntimeType}; -use crate::ssa::ir::instruction::{BinaryOp, Endian, Intrinsic}; +use crate::ssa::ir::instruction::BinaryOp; +use crate::ssa::ir::instruction::Instruction; use crate::ssa::ir::map::AtomicCounter; use crate::ssa::ir::types::{NumericType, Type}; use crate::ssa::ir::value::ValueId; @@ -265,47 +266,211 @@ impl<'a> FunctionContext<'a> { Ok(self.builder.numeric_constant(value, typ)) } - /// Insert ssa instructions which computes lhs << rhs by doing lhs*2^rhs - fn insert_shift_left(&mut self, lhs: ValueId, rhs: ValueId) -> ValueId { - let base = self.builder.field_constant(FieldElement::from(2_u128)); - let pow = self.pow(base, rhs); - let typ = self.builder.current_function.dfg.type_of_value(lhs); - let pow = self.builder.insert_cast(pow, typ); - self.builder.insert_binary(lhs, BinaryOp::Mul, pow) - } - - /// Insert ssa instructions which computes lhs >> rhs by doing lhs/2^rhs - fn insert_shift_right(&mut self, lhs: ValueId, rhs: ValueId) -> ValueId { - let base = self.builder.field_constant(FieldElement::from(2_u128)); - let pow = self.pow(base, rhs); - self.builder.insert_binary(lhs, BinaryOp::Div, pow) - } - - /// Computes lhs^rhs via square&multiply, using the bits decomposition of rhs - fn pow(&mut self, lhs: ValueId, rhs: ValueId) -> ValueId { - let typ = self.builder.current_function.dfg.type_of_value(rhs); - if let Type::Numeric(NumericType::Unsigned { bit_size }) = typ { - let to_bits = self.builder.import_intrinsic_id(Intrinsic::ToBits(Endian::Little)); - let length = self.builder.field_constant(FieldElement::from(bit_size as i128)); - let result_types = - vec![Type::field(), Type::Array(Rc::new(vec![Type::bool()]), bit_size as usize)]; - let rhs_bits = self.builder.insert_call(to_bits, vec![rhs, length], result_types); - let rhs_bits = rhs_bits[1]; - let one = self.builder.field_constant(FieldElement::one()); - let mut r = one; - for i in 1..bit_size + 1 { - let r1 = self.builder.insert_binary(r, BinaryOp::Mul, r); - let a = self.builder.insert_binary(r1, BinaryOp::Mul, lhs); - let idx = self.builder.field_constant(FieldElement::from((bit_size - i) as i128)); - let b = self.builder.insert_array_get(rhs_bits, idx, Type::field()); - let r2 = self.builder.insert_binary(a, BinaryOp::Mul, b); - let c = self.builder.insert_binary(one, BinaryOp::Sub, b); - let r3 = self.builder.insert_binary(c, BinaryOp::Mul, r1); - r = self.builder.insert_binary(r2, BinaryOp::Add, r3); - } - r + /// helper function which add instructions to the block computing the absolute value of the + /// given signed integer input. When the input is negative, we return its two complement, and itself when it is positive. + fn absolute_value_helper(&mut self, input: ValueId, sign: ValueId, bit_size: u32) -> ValueId { + // We compute the absolute value of lhs + let one = self.builder.numeric_constant(FieldElement::one(), Type::bool()); + 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 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 negative_predicate = + self.builder.insert_binary(sign_not_field, BinaryOp::Mul, two_complement); + self.builder.insert_binary(positive_predicate, BinaryOp::Add, negative_predicate) + } + + /// Insert constraints ensuring that the operation does not overflow the bit size of the result + /// + /// If the result is unsigned, we simply range check against the bit size + /// + /// If the result is signed, we just prepare it for check_signed_overflow() by casting it to + /// an unsigned value representing the signed integer. + /// We need to use a bigger bit size depending on the operation, in case the operation does overflow, + /// Then, we delegate the overflow checks to check_signed_overflow() and cast the result back to its type. + /// Note that we do NOT want to check for overflows here, only check_signed_overflow() is allowed to do so. + /// This is because an overflow might be valid. For instance if 'a' is a signed integer, then 'a - a', as an unsigned result will always + /// overflow the bit size, however the operation is still valid (i.e it is not a signed overflow) + fn check_overflow( + &mut self, + result: ValueId, + lhs: ValueId, + rhs: ValueId, + operator: BinaryOpKind, + location: Location, + ) -> ValueId { + let result_type = self.builder.current_function.dfg.type_of_value(result); + match result_type { + Type::Numeric(NumericType::Signed { bit_size }) => { + 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(); + result = self.builder.insert_cast(result, Type::unsigned(bit_size)); + + self.check_signed_overflow(result, lhs, rhs, operator, bit_size, location); + self.builder.insert_cast(result, result_type) + } + BinaryOpKind::Multiply => { + // 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(); + + self.check_signed_overflow(result, lhs, rhs, operator, bit_size, location); + self.builder.insert_cast(result, result_type) + } + BinaryOpKind::ShiftLeft => { + unreachable!("shift is not supported for signed integer") + } + _ => unreachable!("operator {} should not overflow", operator), + } + } + Type::Numeric(NumericType::Unsigned { bit_size }) => { + let op_name = match operator { + BinaryOpKind::Add => "add", + BinaryOpKind::Subtract => "subtract", + BinaryOpKind::Multiply => "multiply", + 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, + } + } else { + result + } + } + _ => result, + } + } + + /// 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 + /// result is the result of the operation, casted into an unsigned integer and not reduced + /// + /// overflow check for signed integer is less straightforward than for unsigned integers. + /// We first compute the sign of the operands, and then we use the following rules: + /// addition: positive operands => result must be positive (i.e less than half the bit size) + /// negative operands => result must be negative (i.e not positive) + /// different sign => no overflow + /// multiplication: we check that the product of the operands' absolute values does not overflow the bit size + /// then we check that the result has the proper sign, using the rule of signs + fn check_signed_overflow( + &mut self, + result: ValueId, + lhs: ValueId, + rhs: ValueId, + operator: BinaryOpKind, + bit_size: u32, + location: Location, + ) { + let is_sub = operator == BinaryOpKind::Subtract; + let one = self.builder.numeric_constant(FieldElement::one(), Type::bool()); + let half_width = self.builder.numeric_constant( + FieldElement::from(2_i128.pow(bit_size - 1)), + Type::unsigned(bit_size), + ); + // We compute the sign of the operands. The overflow checks for signed integers depends on these signs + let lhs_as_unsigned = self.builder.insert_cast(lhs, Type::unsigned(bit_size)); + let rhs_as_unsigned = self.builder.insert_cast(rhs, Type::unsigned(bit_size)); + let lhs_sign = self.builder.insert_binary(lhs_as_unsigned, BinaryOp::Lt, half_width); + let mut rhs_sign = self.builder.insert_binary(rhs_as_unsigned, BinaryOp::Lt, half_width); + let message = if is_sub { + // lhs - rhs = lhs + (-rhs) + rhs_sign = self.builder.insert_binary(one, BinaryOp::Sub, rhs_sign); + "attempt to subtract with overflow".to_string() } else { - unreachable!("Value must be unsigned in power operation"); + "attempt to add with overflow".to_string() + }; + // same_sign is true if both operands have the same sign + let same_sign = self.builder.insert_binary(lhs_sign, BinaryOp::Eq, rhs_sign); + match operator { + BinaryOpKind::Add | BinaryOpKind::Subtract => { + //Check the result has the same sign as its inputs + let result_sign = self.builder.insert_binary(result, BinaryOp::Lt, half_width); + let sign_diff = self.builder.insert_binary(result_sign, BinaryOp::Eq, lhs_sign); + let sign_diff_with_predicate = + self.builder.insert_binary(sign_diff, BinaryOp::Mul, same_sign); + let overflow_check = + Instruction::Constrain(sign_diff_with_predicate, same_sign, Some(message)); + self.builder.set_location(location).insert_instruction(overflow_check, None); + } + BinaryOpKind::Multiply => { + // Overflow check for the multiplication: + // First we compute the absolute value of operands, and their product + let lhs_abs = self.absolute_value_helper(lhs, lhs_sign, bit_size); + let rhs_abs = self.absolute_value_helper(rhs, rhs_sign, bit_size); + let product_field = self.builder.insert_binary(lhs_abs, BinaryOp::Mul, rhs_abs); + // It must not already overflow the bit_size + let message = "attempt to multiply with overflow".to_string(); + let size_overflow = Instruction::RangeCheck { + value: product_field, + max_bit_size: bit_size, + assert_message: Some(message.clone()), + }; + self.builder.set_location(location).insert_instruction(size_overflow, None); + let product = self.builder.insert_cast(product_field, Type::unsigned(bit_size)); + + // 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 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, + ); + } + BinaryOpKind::ShiftLeft => unreachable!("shift is not supported for signed integer"), + _ => unreachable!("operator {} should not overflow", operator), } } @@ -321,8 +486,8 @@ impl<'a> FunctionContext<'a> { location: Location, ) -> Values { let mut result = match operator { - BinaryOpKind::ShiftLeft => self.insert_shift_left(lhs, rhs), - BinaryOpKind::ShiftRight => self.insert_shift_right(lhs, rhs), + BinaryOpKind::ShiftLeft => self.builder.insert_shift_left(lhs, rhs), + BinaryOpKind::ShiftRight => self.builder.insert_shift_right(lhs, rhs), BinaryOpKind::Equal | BinaryOpKind::NotEqual if matches!(self.builder.type_of_value(lhs), Type::Array(..)) => { @@ -338,21 +503,15 @@ impl<'a> FunctionContext<'a> { } }; - if let Some(max_bit_size) = operator_result_max_bit_size_to_truncate( + // Check for integer overflow + if matches!( operator, - lhs, - rhs, - &self.builder.current_function.dfg, + BinaryOpKind::Add + | BinaryOpKind::Subtract + | BinaryOpKind::Multiply + | BinaryOpKind::ShiftLeft ) { - let result_type = self.builder.current_function.dfg.type_of_value(result); - 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"); - } - }; - result = self.builder.insert_truncate(result, bit_size, max_bit_size); + result = self.check_overflow(result, lhs, rhs, operator, location); } if operator_requires_not(operator) { diff --git a/compiler/noirc_frontend/Cargo.toml b/compiler/noirc_frontend/Cargo.toml index 6cc7b07126c..246d6617c94 100644 --- a/compiler/noirc_frontend/Cargo.toml +++ b/compiler/noirc_frontend/Cargo.toml @@ -28,5 +28,4 @@ strum = "0.24" strum_macros = "0.24" [features] -default = [] aztec = [] diff --git a/compiler/noirc_frontend/src/ast/expression.rs b/compiler/noirc_frontend/src/ast/expression.rs index 66b94797822..d29e1670944 100644 --- a/compiler/noirc_frontend/src/ast/expression.rs +++ b/compiler/noirc_frontend/src/ast/expression.rs @@ -370,7 +370,7 @@ pub struct FunctionDefinition { pub visibility: FunctionVisibility, pub generics: UnresolvedGenerics, - pub parameters: Vec<(Pattern, UnresolvedType, Visibility)>, + pub parameters: Vec, pub body: BlockExpression, pub span: Span, pub where_clause: Vec, @@ -379,6 +379,14 @@ pub struct FunctionDefinition { pub return_distinctness: Distinctness, } +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct Param { + pub visibility: Visibility, + pub pattern: Pattern, + pub typ: UnresolvedType, + pub span: Span, +} + #[derive(Debug, PartialEq, Eq, Clone)] pub enum FunctionReturnType { /// Returns type is not specified. @@ -634,8 +642,11 @@ impl FunctionDefinition { ) -> FunctionDefinition { let p = parameters .iter() - .map(|(ident, unresolved_type)| { - (Pattern::Identifier(ident.clone()), unresolved_type.clone(), Visibility::Private) + .map(|(ident, unresolved_type)| Param { + visibility: Visibility::Private, + pattern: Pattern::Identifier(ident.clone()), + typ: unresolved_type.clone(), + span: ident.span().merge(unresolved_type.span.unwrap()), }) .collect(); FunctionDefinition { @@ -661,8 +672,8 @@ impl Display for FunctionDefinition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "{:?}", self.attributes)?; - let parameters = vecmap(&self.parameters, |(name, r#type, visibility)| { - format!("{name}: {visibility} {type}") + let parameters = vecmap(&self.parameters, |Param { visibility, pattern, typ, span: _ }| { + format!("{pattern}: {visibility} {typ}") }); let where_clause = vecmap(&self.where_clause, ToString::to_string); diff --git a/compiler/noirc_frontend/src/ast/function.rs b/compiler/noirc_frontend/src/ast/function.rs index e16c0fcba15..b8f385f52d3 100644 --- a/compiler/noirc_frontend/src/ast/function.rs +++ b/compiler/noirc_frontend/src/ast/function.rs @@ -4,7 +4,7 @@ use noirc_errors::Span; use crate::{ token::{Attributes, FunctionAttribute, SecondaryAttribute}, - FunctionReturnType, Ident, Pattern, Visibility, + FunctionReturnType, Ident, Param, Visibility, }; use super::{FunctionDefinition, UnresolvedType, UnresolvedTypeData}; @@ -45,6 +45,10 @@ impl NoirFunction { NoirFunction { kind: FunctionKind::Oracle, def } } + pub fn return_visibility(&self) -> Visibility { + self.def.return_visibility + } + pub fn return_type(&self) -> UnresolvedType { match &self.def.return_type { FunctionReturnType::Default(_) => { @@ -59,7 +63,7 @@ impl NoirFunction { pub fn name_ident(&self) -> &Ident { &self.def.name } - pub fn parameters(&self) -> &Vec<(Pattern, UnresolvedType, Visibility)> { + pub fn parameters(&self) -> &[Param] { &self.def.parameters } pub fn attributes(&self) -> &Attributes { diff --git a/compiler/noirc_frontend/src/ast/statement.rs b/compiler/noirc_frontend/src/ast/statement.rs index 9fe78f40c59..1ca4d3101a9 100644 --- a/compiler/noirc_frontend/src/ast/statement.rs +++ b/compiler/noirc_frontend/src/ast/statement.rs @@ -1,9 +1,14 @@ use std::fmt::Display; +use std::sync::atomic::{AtomicU32, Ordering}; use crate::lexer::token::SpannedToken; use crate::parser::{ParserError, ParserErrorReason}; use crate::token::Token; -use crate::{Expression, ExpressionKind, IndexExpression, MemberAccessExpression, UnresolvedType}; +use crate::{ + BlockExpression, Expression, ExpressionKind, IndexExpression, MemberAccessExpression, + MethodCallExpression, UnresolvedType, +}; +use acvm::FieldElement; use iter_extended::vecmap; use noirc_errors::{Span, Spanned}; @@ -431,6 +436,14 @@ pub enum Pattern { } impl Pattern { + pub fn span(&self) -> Span { + match self { + Pattern::Identifier(ident) => ident.span(), + Pattern::Mutable(_, span) | Pattern::Tuple(_, span) | Pattern::Struct(_, _, span) => { + *span + } + } + } pub fn name_ident(&self) -> &Ident { match self { Pattern::Identifier(name_ident) => name_ident, @@ -478,12 +491,123 @@ impl LValue { } } +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum ForRange { + Range(/*start:*/ Expression, /*end:*/ Expression), + Array(Expression), +} + +impl ForRange { + /// Create a 'for' expression taking care of desugaring a 'for e in array' loop + /// into the following if needed: + /// + /// { + /// let fresh1 = array; + /// for fresh2 in 0 .. std::array::len(fresh1) { + /// let elem = fresh1[fresh2]; + /// ... + /// } + /// } + pub(crate) fn into_for( + self, + identifier: Ident, + block: Expression, + for_loop_span: Span, + ) -> StatementKind { + /// Counter used to generate unique names when desugaring + /// code in the parser requires the creation of fresh variables. + /// The parser is stateless so this is a static global instead. + static UNIQUE_NAME_COUNTER: AtomicU32 = AtomicU32::new(0); + + match self { + ForRange::Range(..) => { + unreachable!() + } + ForRange::Array(array) => { + let array_span = array.span; + let start_range = ExpressionKind::integer(FieldElement::zero()); + let start_range = Expression::new(start_range, array_span); + + let next_unique_id = UNIQUE_NAME_COUNTER.fetch_add(1, Ordering::Relaxed); + let array_name = format!("$i{next_unique_id}"); + let array_span = array.span; + let array_ident = Ident::new(array_name, array_span); + + // let fresh1 = array; + let let_array = Statement { + kind: StatementKind::Let(LetStatement { + pattern: Pattern::Identifier(array_ident.clone()), + r#type: UnresolvedType::unspecified(), + expression: array, + }), + span: array_span, + }; + + // array.len() + let segments = vec![array_ident]; + let array_ident = + ExpressionKind::Variable(Path { segments, kind: PathKind::Plain }); + + let end_range = ExpressionKind::MethodCall(Box::new(MethodCallExpression { + object: Expression::new(array_ident.clone(), array_span), + method_name: Ident::new("len".to_string(), array_span), + arguments: vec![], + })); + let end_range = Expression::new(end_range, array_span); + + let next_unique_id = UNIQUE_NAME_COUNTER.fetch_add(1, Ordering::Relaxed); + let index_name = format!("$i{next_unique_id}"); + let fresh_identifier = Ident::new(index_name.clone(), array_span); + + // array[i] + let segments = vec![Ident::new(index_name, array_span)]; + let index_ident = + ExpressionKind::Variable(Path { segments, kind: PathKind::Plain }); + + let loop_element = ExpressionKind::Index(Box::new(IndexExpression { + collection: Expression::new(array_ident, array_span), + index: Expression::new(index_ident, array_span), + })); + + // let elem = array[i]; + let let_elem = Statement { + kind: StatementKind::Let(LetStatement { + pattern: Pattern::Identifier(identifier), + r#type: UnresolvedType::unspecified(), + expression: Expression::new(loop_element, array_span), + }), + span: array_span, + }; + + let block_span = block.span; + let new_block = BlockExpression(vec![ + let_elem, + Statement { kind: StatementKind::Expression(block), span: block_span }, + ]); + let new_block = Expression::new(ExpressionKind::Block(new_block), block_span); + let for_loop = Statement { + kind: StatementKind::For(ForLoopStatement { + identifier: fresh_identifier, + range: ForRange::Range(start_range, end_range), + block: new_block, + span: for_loop_span, + }), + span: for_loop_span, + }; + + let block = ExpressionKind::Block(BlockExpression(vec![let_array, for_loop])); + StatementKind::Expression(Expression::new(block, for_loop_span)) + } + } + } +} + #[derive(Debug, PartialEq, Eq, Clone)] pub struct ForLoopStatement { pub identifier: Ident, - pub start_range: Expression, - pub end_range: Expression, + pub range: ForRange, pub block: Expression, + pub span: Span, } impl Display for StatementKind { @@ -575,10 +699,11 @@ impl Display for Pattern { impl Display for ForLoopStatement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "for {} in {} .. {} {}", - self.identifier, self.start_range, self.end_range, self.block - ) + let range = match &self.range { + ForRange::Range(start, end) => format!("{start}..{end}"), + ForRange::Array(expr) => expr.to_string(), + }; + + write!(f, "for {} in {range} {}", self.identifier, self.block) } } diff --git a/compiler/noirc_frontend/src/hir/aztec_library.rs b/compiler/noirc_frontend/src/hir/aztec_library.rs index 24dd79efc6c..3b4703dc60f 100644 --- a/compiler/noirc_frontend/src/hir/aztec_library.rs +++ b/compiler/noirc_frontend/src/hir/aztec_library.rs @@ -16,8 +16,9 @@ use crate::{ UnresolvedType, UnresolvedTypeData, Visibility, }; use crate::{ - ForLoopStatement, FunctionDefinition, FunctionVisibility, ImportStatement, NoirStruct, - PrefixExpression, Signedness, StatementKind, StructType, Type, TypeImpl, UnaryOp, + ForLoopStatement, ForRange, FunctionDefinition, FunctionVisibility, ImportStatement, + NoirStruct, Param, PrefixExpression, Signedness, StatementKind, StructType, Type, TypeImpl, + UnaryOp, }; use fm::FileId; @@ -170,15 +171,9 @@ pub(crate) fn transform( // Covers all functions in the ast for submodule in ast.submodules.iter_mut().filter(|submodule| submodule.is_contract) { - let storage_defined = check_for_storage_definition(&submodule.contents); - - if transform_module(&mut submodule.contents, storage_defined) { - match check_for_aztec_dependency(crate_id, context) { - Ok(()) => include_relevant_imports(&mut submodule.contents), - Err(file_id) => { - return Err((DefCollectorErrorKind::AztecNotFound {}, file_id)); - } - } + if transform_module(&mut submodule.contents, crate_id, context)? { + check_for_aztec_dependency(crate_id, context)?; + include_relevant_imports(&mut submodule.contents); } } Ok(ast) @@ -209,19 +204,59 @@ fn include_relevant_imports(ast: &mut SortedModule) { } /// 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<(), FileId> { +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(crate_graph.root_file_id) + 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(|function| function.name.0.contents == "Storage") + 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 @@ -236,9 +271,26 @@ fn is_custom_attribute(attr: &SecondaryAttribute, attribute_name: &str) -> bool /// 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, storage_defined: bool) -> bool { +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)); @@ -262,7 +314,7 @@ fn transform_module(module: &mut SortedModule, storage_defined: bool) -> bool { has_transformed_module = true; } } - has_transformed_module + Ok(has_transformed_module) } /// If it does, it will insert the following things: @@ -462,14 +514,14 @@ fn generate_selector_impl(structure: &NoirStruct) -> TypeImpl { /// fn foo() { /// // ... /// } -pub(crate) fn create_inputs(ty: &str) -> (Pattern, UnresolvedType, Visibility) { +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; - (context_pattern, context_type, visibility) + 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 @@ -497,7 +549,7 @@ pub(crate) fn create_inputs(ty: &str) -> (Pattern, UnresolvedType, Visibility) { /// let mut context = PrivateContext::new(inputs, hasher.hash()); /// } /// ``` -fn create_context(ty: &str, params: &[(Pattern, UnresolvedType, Visibility)]) -> Vec { +fn create_context(ty: &str, params: &[Param]) -> Vec { let mut injected_expressions: Vec = vec![]; // `let mut hasher = Hasher::new();` @@ -513,7 +565,7 @@ fn create_context(ty: &str, params: &[(Pattern, UnresolvedType, Visibility)]) -> injected_expressions.push(let_hasher); // Iterate over each of the function parameters, adding to them to the hasher - params.iter().for_each(|(pattern, typ, _vis)| { + params.iter().for_each(|Param { pattern, typ, span: _, visibility: _ }| { match pattern { Pattern::Identifier(identifier) => { // Match the type to determine the padding to do @@ -521,8 +573,9 @@ fn create_context(ty: &str, params: &[(Pattern, UnresolvedType, Visibility)]) -> let expression = match unresolved_type { // `hasher.add_multiple({ident}.serialize())` UnresolvedTypeData::Named(..) => add_struct_to_hasher(identifier), - // TODO: if this is an array of structs, we should call serialize on each of them (no methods currently do this yet) - UnresolvedTypeData::Array(..) => add_array_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 @@ -822,6 +875,7 @@ fn add_struct_to_hasher(identifier: &Ident) -> Statement { 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( @@ -836,29 +890,51 @@ fn create_loop_over(var: Expression, loop_body: Vec) -> Statement { // `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"), - start_range: expression(ExpressionKind::Literal(Literal::Integer(FieldElement::from( - i128::from(0), - )))), - end_range: end_range_expression, block: for_loop_block, + span, })) } -fn add_array_to_hasher(identifier: &Ident) -> Statement { +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 cast_expression = cast( - index_array(identifier.clone(), "i"), // lhs - `ident[i]` - UnresolvedTypeData::FieldElement, // cast to - `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 - "add", // method name - vec![cast_expression], + variable("hasher"), // variable + &hasher_method_name, // method name + vec![add_expression], ))); create_loop_over(variable_ident(identifier.clone()), vec![block_statement]) 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 aa2bedb37b7..ce1cf675a07 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -1,7 +1,7 @@ use super::dc_mod::collect_defs; use super::errors::{DefCollectorErrorKind, DuplicateType}; use crate::graph::CrateId; -use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleDefId, ModuleId}; +use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleData, ModuleDefId, ModuleId}; use crate::hir::resolution::errors::ResolverError; use crate::hir::resolution::import::PathResolutionError; use crate::hir::resolution::path_resolver::PathResolver; @@ -14,14 +14,14 @@ 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, TraitImplKey, TypeAliasId, + FuncId, NodeInterner, StmtId, StructId, TraitId, TraitImplId, 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, UnresolvedType, + UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, }; use fm::FileId; use iter_extended::vecmap; @@ -92,6 +92,8 @@ pub struct UnresolvedTraitImpl { pub trait_path: Path, pub object_type: UnresolvedType, pub methods: UnresolvedFunctions, + pub generics: UnresolvedGenerics, + pub where_clause: Vec, } #[derive(Clone)] @@ -126,7 +128,7 @@ pub struct DefCollector { pub enum CompilationError { ParseError(ParserError), DefinitionError(DefCollectorErrorKind), - ResolveError(ResolverError), + ResolverError(ResolverError), TypeError(TypeCheckError), } @@ -135,7 +137,7 @@ impl From for CustomDiagnostic { match value { CompilationError::ParseError(error) => error.into(), CompilationError::DefinitionError(error) => error.into(), - CompilationError::ResolveError(error) => error.into(), + CompilationError::ResolverError(error) => error.into(), CompilationError::TypeError(error) => error.into(), } } @@ -155,7 +157,7 @@ impl From for CompilationError { impl From for CompilationError { fn from(value: ResolverError) -> Self { - CompilationError::ResolveError(value) + CompilationError::ResolverError(value) } } impl From for CompilationError { @@ -296,12 +298,6 @@ impl DefCollector { // globals will need to reference the struct type they're initialized to to ensure they are valid. resolved_globals.extend(resolve_globals(context, other_globals, crate_id)); - // Before we resolve any function symbols we must go through our impls and - // re-collect the methods within into their proper module. This cannot be - // done before resolution since we need to be able to resolve the type of the - // impl since that determines the module we should collect into. - errors.extend(collect_impls(context, crate_id, &def_collector.collected_impls)); - // Bind trait impls to their trait. Collect trait functions, that have a // default implementation, which hasn't been overridden. errors.extend(collect_trait_impls( @@ -310,6 +306,15 @@ impl DefCollector { &mut def_collector.collected_traits_impls, )); + // Before we resolve any function symbols we must go through our impls and + // re-collect the methods within into their proper module. This cannot be + // done before resolution since we need to be able to resolve the type of the + // impl since that determines the module we should collect into. + // + // These are resolved after trait impls so that struct methods are chosen + // over trait methods if there are name conflicts. + errors.extend(collect_impls(context, crate_id, &def_collector.collected_impls)); + // Lower each function in the crate. This is now possible since imports have been resolved let file_func_ids = resolve_free_functions( &mut context.def_interner, @@ -327,7 +332,6 @@ impl DefCollector { def_collector.collected_impls, &mut errors, ); - // resolve_trait_impls can fill different type of errors, therefore we pass errors by mut ref let file_trait_impls_ids = resolve_trait_impls( context, def_collector.collected_traits_impls, @@ -377,7 +381,6 @@ fn collect_impls( if let Some(struct_type) = get_struct_type(&typ) { let struct_type = struct_type.borrow(); - let type_module = struct_type.id.local_module_id(); // `impl`s are only allowed on types defined within the current crate if struct_type.id.krate() != crate_id { @@ -391,7 +394,7 @@ fn collect_impls( // 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 = &mut def_maps.get_mut(&crate_id).unwrap().modules[type_module.0]; + 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 @@ -413,6 +416,13 @@ fn collect_impls( 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, @@ -494,25 +504,6 @@ fn collect_trait_impl_methods( errors } -fn add_method_to_struct_namespace( - current_def_map: &mut CrateDefMap, - struct_type: &Shared, - func_id: FuncId, - name_ident: &Ident, - trait_id: TraitId, -) -> Result<(), DefCollectorErrorKind> { - let struct_type = struct_type.borrow(); - let type_module = struct_type.id.local_module_id(); - let module = &mut current_def_map.modules[type_module.0]; - module.declare_trait_function(name_ident.clone(), func_id, trait_id).map_err( - |(first_def, second_def)| DefCollectorErrorKind::Duplicate { - typ: DuplicateType::TraitImplementation, - first_def, - second_def, - }, - ) -} - fn collect_trait_impl( context: &mut Context, crate_id: CrateId, @@ -535,28 +526,25 @@ fn collect_trait_impl( if let Some(trait_id) = trait_impl.trait_id { errors .extend(collect_trait_impl_methods(interner, def_maps, crate_id, trait_id, trait_impl)); - for (_, func_id, ast) in &trait_impl.methods.functions { - let file = def_maps[&crate_id].file_id(trait_impl.module_id); - - let path_resolver = StandardPathResolver::new(module); - let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); - resolver.add_generics(&ast.def.generics); - let typ = resolver.resolve_type(unresolved_type.clone()); - if let Some(struct_type) = get_struct_type(&typ) { - errors.extend(take_errors(trait_impl.file_id, resolver)); - let current_def_map = def_maps.get_mut(&struct_type.borrow().id.krate()).unwrap(); - match add_method_to_struct_namespace( - current_def_map, - struct_type, - *func_id, - ast.name_ident(), - trait_id, - ) { - Ok(()) => {} - Err(err) => { - errors.push((err.into(), trait_impl.file_id)); - } + 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()); } } } @@ -772,7 +760,7 @@ fn resolve_trait_methods( for item in &unresolved_trait.trait_def.items { if let TraitItem::Function { name, - generics: _, + generics, parameters, return_type, where_clause: _, @@ -784,14 +772,14 @@ fn resolve_trait_methods( 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(); - // TODO - let generics: Generics = vec![]; let span: Span = name.span(); let default_impl_list: Vec<_> = unresolved_trait .fns_with_default_impl @@ -841,7 +829,7 @@ fn take_errors_filter_self_not_resolved( } fn take_errors(file_id: FileId, resolver: Resolver<'_>) -> Vec<(CompilationError, FileId)> { - resolver.take_errors().iter().cloned().map(|e| (e.into(), file_id)).collect() + vecmap(resolver.take_errors(), |e| (e.into(), file_id)) } /// Create the mappings from TypeId -> TraitType @@ -934,6 +922,7 @@ fn resolve_impls( def_maps, functions, Some(self_type.clone()), + None, generics, errors, ); @@ -942,7 +931,7 @@ fn resolve_impls( 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) + interner.add_method(&self_type, method_name.clone(), *method_id, false) { let error = ResolverError::DuplicateDefinition { name: method_name, @@ -974,17 +963,16 @@ fn resolve_trait_impls( 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 trait_definition_ident = trait_impl.trait_path.last_segment(); let self_type_span = unresolved_type.span; - let self_type = { - let mut resolver = - Resolver::new(interner, &path_resolver, &context.def_maps, trait_impl.file_id); - resolver.resolve_type(unresolved_type.clone()) - }; + 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 maybe_trait_id = trait_impl.trait_id; + let impl_id = interner.next_trait_impl_id(); let mut impl_methods = resolve_function_set( interner, @@ -992,45 +980,70 @@ fn resolve_trait_impls( &context.def_maps, trait_impl.methods.clone(), Some(self_type.clone()), - vec![], // TODO + 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, errors); - - let key = TraitImplKey { typ: self_type.clone(), trait_id }; - if let Some(prev_trait_impl_ident) = interner.get_trait_implementation(&key) { - let err = DefCollectorErrorKind::Duplicate { - typ: DuplicateType::TraitImplementation, - first_def: prev_trait_impl_ident.borrow().ident.clone(), - second_def: trait_definition_ident.clone(), - }; - errors.push((err.into(), trait_impl.methods.file_id)); - } else { - let resolved_trait_impl = Shared::new(TraitImpl { - ident: trait_impl.trait_path.last_segment().clone(), + 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(), - trait_id, - methods: vecmap(&impl_methods, |(_, func_id)| *func_id), - }); - if !interner.add_trait_implementation(&key, resolved_trait_impl.clone()) { - let error = DefCollectorErrorKind::TraitImplNotAllowedFor { - trait_path: trait_impl.trait_path.clone(), - span: self_type_span.unwrap_or_else(|| trait_impl.trait_path.span()), - }; - errors.push((error.into(), trait_impl.file_id)); - } + 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); @@ -1045,6 +1058,7 @@ 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); @@ -1055,24 +1069,42 @@ fn check_methods_signatures( let _ = the_trait.self_type_typevar.borrow_mut().bind_to(self_type.clone(), the_trait.span); for (file_id, func_id) in impl_methods { - let meta = resolver.interner.function_meta(func_id); + let impl_method = resolver.interner.function_meta(func_id); let func_name = resolver.interner.function_name(func_id).to_owned(); let mut typecheck_errors = Vec::new(); - // `method` is None in the case where the impl block has a method that's not part of the trait. + // This is None in the case where the impl block has a method that's not part of the trait. // 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(method) = + if let Some(trait_method) = the_trait.methods.iter().find(|method| method.name.0.contents == func_name) { - let function_typ = meta.typ.instantiate(resolver.interner); + 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(); + + 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(), + method_name: func_name.to_string(), + span: impl_method.location.span, + }; + errors.push((error.into(), *file_id)); + } - if let Type::Function(params, _, _) = function_typ.0 { - if method.arguments.len() == params.len() { + if let Type::Function(impl_params, _, _) = impl_function_type.0 { + 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_and_params = args.zip(&impl_params).zip(&impl_method.parameters.0); + for (parameter_index, ((expected, actual), (hir_pattern, _, _))) in - method.arguments.iter().zip(¶ms).zip(&meta.parameters.0).enumerate() + args_and_params.enumerate() { expected.unify(actual, &mut typecheck_errors, || { TypeCheckError::TraitMethodParameterTypeMismatch { @@ -1085,33 +1117,28 @@ fn check_methods_signatures( }); } } else { - errors.push(( - DefCollectorErrorKind::MismatchTraitImplementationNumParameters { - actual_num_parameters: meta.parameters.0.len(), - expected_num_parameters: method.arguments.len(), - trait_name: the_trait.name.to_string(), - method_name: func_name.to_string(), - span: meta.location.span, - } - .into(), - *file_id, - )); + 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(), + method_name: func_name.to_string(), + span: impl_method.location.span, + }; + errors.push((error.into(), *file_id)); } } // Check that impl method return type matches trait return type: let resolved_return_type = - resolver.resolve_type(meta.return_type.get_type().into_owned()); + resolver.resolve_type(impl_method.return_type.get_type().into_owned()); - method.return_type.unify(&resolved_return_type, &mut typecheck_errors, || { - let ret_type_span = - meta.return_type.get_type().span.expect("return type must always have a span"); + 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"); - TypeCheckError::TypeMismatch { - expected_typ: method.return_type.to_string(), - expr_typ: meta.return_type().to_string(), - expr_span: ret_type_span, - } + 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 } }); errors.extend(typecheck_errors.iter().cloned().map(|e| (e.into(), *file_id))); @@ -1139,6 +1166,7 @@ fn resolve_free_functions( def_maps, unresolved_functions, self_type.clone(), + None, vec![], // no impl generics errors, ) @@ -1146,12 +1174,14 @@ fn resolve_free_functions( .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)> { @@ -1172,6 +1202,7 @@ fn resolve_function_set( 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() { 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 ed48d7fbb51..17aa5e9951f 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -7,7 +7,7 @@ use noirc_errors::Location; use crate::{ graph::CrateId, hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait}, - node_interner::{TraitId, TypeAliasId}, + node_interner::{FunctionModifiers, TraitId, TypeAliasId}, parser::{SortedModule, SortedSubModule}, FunctionDefinition, Ident, LetStatement, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, TraitImplItem, TraitItem, TypeImpl, @@ -145,12 +145,13 @@ impl<'a> ModCollector<'a> { for trait_impl in impls { let trait_name = trait_impl.trait_name.clone(); - let unresolved_functions = + let mut unresolved_functions = self.collect_trait_impl_function_overrides(context, &trait_impl, krate); let module = ModuleId { krate, local_id: self.module_id }; - for (_, func_id, noir_function) in &unresolved_functions.functions { + 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); } @@ -160,6 +161,8 @@ impl<'a> ModCollector<'a> { trait_path: trait_name, methods: unresolved_functions, object_type: trait_impl.object_type, + generics: trait_impl.impl_generics, + where_clause: trait_impl.where_clause, trait_id: None, // will be filled later }; @@ -378,11 +381,22 @@ impl<'a> ModCollector<'a> { body, } => { let func_id = context.def_interner.push_empty_fn(); + let modifiers = FunctionModifiers { + name: name.to_string(), + visibility: crate::FunctionVisibility::Public, + // TODO(Maddiaa): Investigate trait implementations with attributes see: https://github.com/noir-lang/noir/issues/2629 + attributes: crate::token::Attributes::empty(), + is_unconstrained: false, + contract_function_type: None, + is_internal: None, + }; + + context.def_interner.push_function_definition(func_id, modifiers, id.0); + match self.def_collector.def_map.modules[id.0.local_id.0] .declare_function(name.clone(), func_id) { Ok(()) => { - // TODO(Maddiaa): Investigate trait implementations with attributes see: https://github.com/noir-lang/noir/issues/2629 if let Some(body) = body { let impl_method = NoirFunction::normal(FunctionDefinition::normal( diff --git a/compiler/noirc_frontend/src/hir/def_collector/errors.rs b/compiler/noirc_frontend/src/hir/def_collector/errors.rs index 4e7f8ad286b..edb39fe68d7 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/errors.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/errors.rs @@ -33,11 +33,15 @@ pub enum DefCollectorErrorKind { PathResolutionError(PathResolutionError), #[error("Non-struct type used in impl")] NonStructTypeInImpl { span: Span }, - #[error("Trait implementation is not allowed for this")] - TraitImplNotAllowedFor { trait_path: Path, span: Span }, + #[error("Cannot implement trait on a mutable reference type")] + MutableReferenceInTraitImpl { span: Span }, + #[error("Impl for type `{typ}` overlaps with existing impl")] + OverlappingImpl { span: Span, typ: crate::Type }, + #[error("Previous impl defined here")] + OverlappingImplNote { span: Span }, #[error("Cannot `impl` a type defined outside the current crate")] ForeignImpl { span: Span, type_name: String }, - #[error("Mismatch number of parameters in of trait implementation")] + #[error("Mismatched number of parameters in trait implementation")] MismatchTraitImplementationNumParameters { actual_num_parameters: usize, expected_num_parameters: usize, @@ -45,6 +49,14 @@ pub enum DefCollectorErrorKind { method_name: String, span: Span, }, + #[error("Mismatched number of generics in impl method")] + MismatchTraitImplementationNumGenerics { + impl_method_generic_count: usize, + trait_method_generic_count: usize, + trait_name: String, + method_name: String, + span: Span, + }, #[error("Method is not defined in trait")] MethodNotInTrait { trait_name: Ident, impl_method: Ident }, #[error("Only traits can be implemented")] @@ -57,13 +69,19 @@ pub enum DefCollectorErrorKind { ModuleAlreadyPartOfCrate { mod_name: Ident, span: Span }, #[error("Module was originally declared here")] ModuleOriginallyDefined { mod_name: Ident, span: Span }, - #[cfg(feature = "aztec")] - #[error("Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml")] - AztecNotFound {}, #[error( "Either the type or the trait must be from the same crate as the trait implementation" )] TraitImplOrphaned { span: Span }, + + // 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 }, } impl DefCollectorErrorKind { @@ -125,10 +143,25 @@ impl From for Diagnostic { "Only struct types may have implementation methods".into(), span, ), - DefCollectorErrorKind::TraitImplNotAllowedFor { trait_path, span } => { + DefCollectorErrorKind::MutableReferenceInTraitImpl { span } => Diagnostic::simple_error( + "Trait impls are not allowed on mutable reference types".into(), + "Try using a struct type here instead".into(), + span, + ), + DefCollectorErrorKind::OverlappingImpl { span, typ } => { + Diagnostic::simple_error( + format!("Impl for type `{typ}` overlaps with existing impl"), + "Overlapping impl".into(), + span, + ) + } + DefCollectorErrorKind::OverlappingImplNote { span } => { + // This should be a note or part of the previous error eventually. + // This must be an error to appear next to the previous OverlappingImpl + // error since we sort warnings first. Diagnostic::simple_error( - format!("Only limited types may implement trait `{trait_path}`"), - "Only limited types may implement traits".into(), + "Previous impl defined here".into(), + "Previous impl defined here".into(), span, ) } @@ -149,8 +182,21 @@ impl From for Diagnostic { method_name, span, } => { + let plural = if expected_num_parameters == 1 { "" } else { "s" }; let primary_message = format!( - "Method `{method_name}` of trait `{trait_name}` needs {expected_num_parameters} parameters, but has {actual_num_parameters}"); + "`{trait_name}::{method_name}` expects {expected_num_parameters} parameter{plural}, but this method has {actual_num_parameters}"); + Diagnostic::simple_error(primary_message, "".to_string(), span) + } + DefCollectorErrorKind::MismatchTraitImplementationNumGenerics { + impl_method_generic_count, + trait_method_generic_count, + trait_name, + method_name, + span, + } => { + let plural = if trait_method_generic_count == 1 { "" } else { "s" }; + let primary_message = format!( + "`{trait_name}::{method_name}` expects {trait_method_generic_count} generic{plural}, but this method has {impl_method_generic_count}"); Diagnostic::simple_error(primary_message, "".to_string(), span) } DefCollectorErrorKind::MethodNotInTrait { trait_name, impl_method } => { @@ -194,15 +240,21 @@ impl From for Diagnostic { let secondary = String::new(); Diagnostic::simple_error(message, secondary, span) } - #[cfg(feature = "aztec")] - DefCollectorErrorKind::AztecNotFound {} => Diagnostic::from_message( - "Aztec dependency not found. Please add aztec as a dependency in your Cargo.toml", - ), DefCollectorErrorKind::TraitImplOrphaned { span } => Diagnostic::simple_error( "Orphaned trait implementation".into(), "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 + ), } } } diff --git a/compiler/noirc_frontend/src/hir/mod.rs b/compiler/noirc_frontend/src/hir/mod.rs index aabb0e82daa..5a28d7b779a 100644 --- a/compiler/noirc_frontend/src/hir/mod.rs +++ b/compiler/noirc_frontend/src/hir/mod.rs @@ -7,7 +7,7 @@ pub mod type_check; #[cfg(feature = "aztec")] pub(crate) mod aztec_library; -use crate::graph::{CrateGraph, CrateId, Dependency}; +use crate::graph::{CrateGraph, CrateId}; use crate::hir_def::function::FuncMeta; use crate::node_interner::{FuncId, NodeInterner, StructId}; use def_map::{Contract, CrateDefMap}; @@ -119,18 +119,35 @@ impl Context { if &module_id.krate == crate_id { module_path } else { - let crate_name = &self.crate_graph[crate_id] - .dependencies - .iter() - .find_map(|dep| match dep { - Dependency { name, crate_id } if crate_id == &module_id.krate => Some(name), - _ => None, - }) + let crates = self + .find_dependencies(crate_id, &module_id.krate) .expect("The Struct was supposed to be defined in a dependency"); - format!("{crate_name}::{module_path}") + crates.join("::") + "::" + &module_path } } + /// Recursively walks down the crate dependency graph from crate_id until we reach requested crate + /// This is needed in case a library (lib1) re-export a structure defined in another library (lib2) + /// In that case, we will get [lib1,lib2] when looking for a struct defined in lib2, + /// re-exported by lib1 and used by the main crate. + /// Returns the path from crate_id to target_crate_id + fn find_dependencies( + &self, + crate_id: &CrateId, + target_crate_id: &CrateId, + ) -> Option> { + for dep in &self.crate_graph[crate_id].dependencies { + if &dep.crate_id == target_crate_id { + return Some(vec![dep.name.to_string()]); + } + if let Some(mut path) = self.find_dependencies(&dep.crate_id, target_crate_id) { + path.insert(0, dep.name.to_string()); + return Some(path); + } + } + None + } + pub fn function_meta(&self, func_id: &FuncId) -> FuncMeta { self.def_interner.function_meta(func_id) } diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index b3796418ab3..4b829932b76 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -29,6 +29,7 @@ use crate::hir::def_map::{LocalModuleId, ModuleDefId, TryFromModuleDefId, MAIN_F use crate::hir_def::stmt::{HirAssignStatement, HirForStatement, HirLValue, HirPattern}; use crate::node_interner::{ DefinitionId, DefinitionKind, ExprId, FuncId, NodeInterner, StmtId, StructId, TraitId, + TraitImplId, TraitImplKind, }; use crate::{ hir::{def_map::CrateDefMap, resolution::path_resolver::PathResolver}, @@ -36,10 +37,11 @@ use crate::{ StatementKind, }; use crate::{ - ArrayLiteral, ContractFunctionType, Distinctness, FunctionVisibility, Generics, LValue, - NoirStruct, NoirTypeAlias, Path, PathKind, Pattern, Shared, StructType, Type, TypeAliasType, - TypeBinding, TypeVariable, UnaryOp, UnresolvedGenerics, UnresolvedTraitConstraint, - UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, Visibility, ERROR_IDENT, + 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, }; use fm::FileId; use iter_extended::vecmap; @@ -87,6 +89,10 @@ pub struct Resolver<'a> { /// Set to the current type if we're resolving an impl self_type: Option, + /// If we're currently resolving methods within a trait impl, this will be set + /// to the corresponding trait impl ID. + current_trait_impl: Option, + /// True if the current module is a contract. /// This is usually determined by self.path_resolver.module_id(), but it can /// be overriden for impls. Impls are an odd case since the methods within resolve @@ -141,6 +147,7 @@ impl<'a> Resolver<'a> { generics: Vec::new(), errors: Vec::new(), lambda_stack: Vec::new(), + current_trait_impl: None, file, in_contract, } @@ -154,6 +161,10 @@ impl<'a> Resolver<'a> { self.trait_id = trait_id; } + pub fn set_trait_impl_id(&mut self, impl_id: Option) { + self.current_trait_impl = impl_id; + } + pub fn get_self_type(&mut self) -> Option<&Type> { self.self_type.as_ref() } @@ -356,6 +367,15 @@ impl<'a> Resolver<'a> { (hir_func, func_meta) } + pub fn resolve_trait_constraint( + &mut self, + constraint: UnresolvedTraitConstraint, + ) -> Option { + let typ = self.resolve_type(constraint.typ); + let trait_id = self.lookup_trait_or_error(constraint.trait_bound.trait_path)?.id; + Some(TraitConstraint { typ, trait_id }) + } + /// Translates an UnresolvedType into a Type and appends any /// freshly created TypeVariables created to new_variables. fn resolve_type_inner(&mut self, typ: UnresolvedType, new_variables: &mut Generics) -> Type { @@ -740,7 +760,7 @@ impl<'a> Resolver<'a> { let mut parameters = vec![]; let mut parameter_types = vec![]; - for (pattern, typ, visibility) in func.parameters().iter().cloned() { + for Param { visibility, pattern, typ, span: _ } in func.parameters().iter().cloned() { if visibility == Visibility::Public && !self.pub_allowed(func) { self.push_err(ResolverError::UnnecessaryPub { ident: func.name_ident().clone(), @@ -808,6 +828,7 @@ impl<'a> Resolver<'a> { kind: func.kind, location, typ, + trait_impl: self.current_trait_impl, parameters: parameters.into(), return_type: func.def.return_type.clone(), return_visibility: func.def.return_visibility, @@ -1007,23 +1028,37 @@ impl<'a> Resolver<'a> { HirStatement::Assign(stmt) } StatementKind::For(for_loop) => { - let start_range = self.resolve_expression(for_loop.start_range); - let end_range = self.resolve_expression(for_loop.end_range); - let (identifier, block) = (for_loop.identifier, for_loop.block); - - // TODO: For loop variables are currently mutable by default since we haven't - // yet implemented syntax for them to be optionally mutable. - let (identifier, block) = self.in_new_scope(|this| { - let decl = this.add_variable_decl( - identifier, - false, - true, - DefinitionKind::Local(None), - ); - (decl, this.resolve_expression(block)) - }); + match for_loop.range { + ForRange::Range(start_range, end_range) => { + let start_range = self.resolve_expression(start_range); + let end_range = self.resolve_expression(end_range); + let (identifier, block) = (for_loop.identifier, for_loop.block); + + // TODO: For loop variables are currently mutable by default since we haven't + // yet implemented syntax for them to be optionally mutable. + let (identifier, block) = self.in_new_scope(|this| { + let decl = this.add_variable_decl( + identifier, + false, + true, + DefinitionKind::Local(None), + ); + (decl, this.resolve_expression(block)) + }); - HirStatement::For(HirForStatement { start_range, end_range, block, identifier }) + HirStatement::For(HirForStatement { + start_range, + end_range, + block, + identifier, + }) + } + range @ ForRange::Array(_) => { + let for_stmt = + range.into_for(for_loop.identifier, for_loop.block, for_loop.span); + self.resolve_stmt(for_stmt) + } + } } StatementKind::Error => HirStatement::Error, } @@ -1172,8 +1207,12 @@ impl<'a> Resolver<'a> { Literal::Unit => HirLiteral::Unit, }), ExpressionKind::Variable(path) => { - if let Some(expr) = self.resolve_trait_generic_path(&path) { - expr + if let Some((hir_expr, object_type)) = self.resolve_trait_generic_path(&path) { + let expr_id = self.interner.push_expr(hir_expr); + self.interner.push_expr_location(expr_id, expr.span, self.file); + self.interner + .select_impl_for_ident(expr_id, TraitImplKind::Assumed { object_type }); + return expr_id; } else { // If the Path is being used as an Expression, then it is referring to a global from a separate module // Otherwise, then it is referring to an Identifier @@ -1335,6 +1374,8 @@ impl<'a> Resolver<'a> { ExpressionKind::Parenthesized(sub_expr) => return self.resolve_expression(*sub_expr), }; + // If these lines are ever changed, make sure to change the early return + // in the ExpressionKind::Variable case as well let expr_id = self.interner.push_expr(hir_expr); self.interner.push_expr_location(expr_id, expr.span, self.file); expr_id @@ -1541,7 +1582,10 @@ impl<'a> Resolver<'a> { } // this resolves Self::some_static_method, inside an impl block (where we don't have a concrete self_type) - fn resolve_trait_static_method_by_self(&mut self, path: &Path) -> Option { + fn resolve_trait_static_method_by_self( + &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; @@ -1555,7 +1599,7 @@ impl<'a> Resolver<'a> { the_trait.self_type_typevar, crate::TypeVariableKind::Normal, ); - return Some(HirExpression::TraitMethodReference(self_type, method)); + return Some((HirExpression::TraitMethodReference(method), self_type)); } } } @@ -1564,7 +1608,10 @@ impl<'a> Resolver<'a> { } // this resolves a static trait method T::trait_method by iterating over the where clause - fn resolve_trait_method_by_named_generic(&mut self, path: &Path) -> Option { + fn resolve_trait_method_by_named_generic( + &mut self, + path: &Path, + ) -> Option<(HirExpression, Type)> { if path.segments.len() != 2 { return None; } @@ -1586,7 +1633,7 @@ impl<'a> Resolver<'a> { the_trait.find_method(path.segments.last().unwrap().clone()) { let self_type = self.resolve_type(typ.clone()); - return Some(HirExpression::TraitMethodReference(self_type, method)); + return Some((HirExpression::TraitMethodReference(method), self_type)); } } } @@ -1594,7 +1641,7 @@ impl<'a> Resolver<'a> { None } - fn resolve_trait_generic_path(&mut self, path: &Path) -> Option { + 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_method_by_named_generic(path)) } diff --git a/compiler/noirc_frontend/src/hir/type_check/errors.rs b/compiler/noirc_frontend/src/hir/type_check/errors.rs index b2b360dc81e..267dbd6b5be 100644 --- a/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -111,6 +111,10 @@ pub enum TypeCheckError { parameter_span: Span, parameter_index: usize, }, + #[error("No matching impl found")] + NoMatchingImplFound { constraints: Vec<(Type, String)>, span: Span }, + #[error("Constraint for `{typ}: {trait_name}` is not needed, another matching impl is already in scope")] + UnneededTraitConstraint { trait_name: String, typ: Type, span: Span }, } impl TypeCheckError { @@ -250,11 +254,26 @@ impl From for Diagnostic { Diagnostic::simple_warning(primary_message, secondary_message, span) } TypeCheckError::UnusedResultError { expr_type, expr_span } => { - Diagnostic::simple_warning( - format!("Unused expression result of type {expr_type}"), - String::new(), - expr_span, - ) + let msg = format!("Unused expression result of type {expr_type}"); + Diagnostic::simple_warning(msg, String::new(), expr_span) + } + TypeCheckError::NoMatchingImplFound { constraints, span } => { + assert!(!constraints.is_empty()); + let msg = format!("No matching impl found for `{}: {}`", constraints[0].0, constraints[0].1); + let mut diagnostic = Diagnostic::from_message(&msg); + + diagnostic.add_secondary(format!("No impl for `{}: {}`", constraints[0].0, constraints[0].1), span); + + // These must be notes since secondaries are unordered + for (typ, trait_name) in &constraints[1..] { + diagnostic.add_note(format!("Required by `{typ}: {trait_name}`")); + } + + diagnostic + } + TypeCheckError::UnneededTraitConstraint { trait_name, typ, span } => { + let msg = format!("Constraint for `{typ}: {trait_name}` is not needed, another matching impl is already in scope"); + Diagnostic::simple_warning(msg, "Unnecessary trait constraint in where clause".into(), span) } } } diff --git a/compiler/noirc_frontend/src/hir/type_check/expr.rs b/compiler/noirc_frontend/src/hir/type_check/expr.rs index 7f21bdbebda..74f076212fa 100644 --- a/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -10,7 +10,7 @@ use crate::{ }, types::Type, }, - node_interner::{DefinitionKind, ExprId, FuncId, TraitMethodId}, + node_interner::{DefinitionKind, ExprId, FuncId, TraitId, TraitMethodId}, BinaryOpKind, Signedness, TypeBinding, TypeVariableKind, UnaryOp, }; @@ -53,6 +53,19 @@ impl<'interner> TypeChecker<'interner> { // variable to handle generic functions. let t = self.interner.id_type_substitute_trait_as_type(ident.id); let (typ, bindings) = t.instantiate(self.interner); + + // Push any trait constraints required by this definition to the context + // to be checked later when the type of this variable is further constrained. + if let Some(definition) = self.interner.try_definition(ident.id) { + if let DefinitionKind::Function(function) = definition.kind { + let function = self.interner.function_meta(&function); + for mut constraint in function.trait_constraints.clone() { + constraint.typ = constraint.typ.substitute(&bindings); + self.trait_constraints.push((constraint, *expr_id)); + } + } + } + self.interner.store_instantiation_bindings(*expr_id, bindings); typ } @@ -132,7 +145,9 @@ impl<'interner> TypeChecker<'interner> { HirExpression::Index(index_expr) => self.check_index_expression(expr_id, index_expr), HirExpression::Call(call_expr) => { self.check_if_deprecated(&call_expr.func); + let function = self.check_expression(&call_expr.func); + let args = vecmap(&call_expr.arguments, |arg| { let typ = self.check_expression(arg); (typ, *arg, self.interner.expr_span(arg)) @@ -146,7 +161,7 @@ impl<'interner> TypeChecker<'interner> { match self.lookup_method(&object_type, method_name, expr_id) { Some(method_ref) => { let mut args = vec![( - object_type, + object_type.clone(), method_call.object, self.interner.expr_span(&method_call.object), )]; @@ -160,18 +175,29 @@ impl<'interner> TypeChecker<'interner> { // so that the backend doesn't need to worry about methods let location = method_call.location; - if let HirMethodReference::FuncId(func_id) = method_ref { - // Automatically add `&mut` if the method expects a mutable reference and - // the object is not already one. - if func_id != FuncId::dummy_id() { - let func_meta = self.interner.function_meta(&func_id); - self.try_add_mutable_reference_to_object( - &mut method_call, - &func_meta.typ, - &mut args, - ); + let trait_id = match &method_ref { + HirMethodReference::FuncId(func_id) => { + // Automatically add `&mut` if the method expects a mutable reference and + // the object is not already one. + if *func_id != FuncId::dummy_id() { + let func_meta = self.interner.function_meta(func_id); + self.try_add_mutable_reference_to_object( + &mut method_call, + &func_meta.typ, + &mut args, + ); + } + + let meta = self.interner.function_meta(func_id); + meta.trait_impl.map(|impl_id| { + self.interner + .get_trait_implementation(impl_id) + .borrow() + .trait_id + }) } - } + HirMethodReference::TraitMethodId(method) => Some(method.trait_id), + }; let (function_id, function_call) = method_call.into_function_call( method_ref.clone(), @@ -182,6 +208,10 @@ impl<'interner> TypeChecker<'interner> { let span = self.interner.expr_span(expr_id); let ret = self.check_method_call(&function_id, method_ref, args, span); + if let Some(trait_id) = trait_id { + self.verify_trait_constraint(&object_type, trait_id, function_id, span); + } + self.interner.replace_expr(expr_id, function_call); ret } @@ -257,7 +287,7 @@ impl<'interner> TypeChecker<'interner> { Type::Function(params, Box::new(lambda.return_type), Box::new(env_type)) } - HirExpression::TraitMethodReference(_, method) => { + HirExpression::TraitMethodReference(method) => { let the_trait = self.interner.get_trait(method.trait_id); let method = &the_trait.methods[method.method_index]; @@ -266,6 +296,7 @@ impl<'interner> TypeChecker<'interner> { Box::new(method.return_type.clone()), Box::new(Type::Unit), ); + let (typ, bindings) = typ.instantiate(self.interner); self.interner.store_instantiation_bindings(*expr_id, bindings); typ @@ -276,6 +307,33 @@ impl<'interner> TypeChecker<'interner> { typ } + pub fn verify_trait_constraint( + &mut self, + object_type: &Type, + trait_id: TraitId, + function_ident_id: ExprId, + span: Span, + ) { + match self.interner.lookup_trait_implementation(object_type, trait_id) { + Ok(impl_kind) => self.interner.select_impl_for_ident(function_ident_id, impl_kind), + Err(erroring_constraints) => { + // Don't show any errors where try_get_trait returns None. + // This can happen if a trait is used that was never declared. + let constraints = erroring_constraints + .into_iter() + .map(|constraint| { + let r#trait = self.interner.try_get_trait(constraint.trait_id)?; + Some((constraint.typ, r#trait.name.to_string())) + }) + .collect::>>(); + + if let Some(constraints) = constraints { + self.errors.push(TypeCheckError::NoMatchingImplFound { constraints, span }); + } + } + } + } + /// Check if the given method type requires a mutable reference to the object type, and check /// if the given object type is already a mutable reference. If not, add one. /// This is used to automatically transform a method call: `foo.bar()` into a function @@ -293,9 +351,9 @@ impl<'interner> TypeChecker<'interner> { argument_types: &mut [(Type, ExprId, noirc_errors::Span)], ) { let expected_object_type = match function_type { - Type::Function(args, _, _) => args.get(0), + Type::Function(args, _, _) => args.first(), Type::Forall(_, typ) => match typ.as_ref() { - Type::Function(args, _, _) => args.get(0), + Type::Function(args, _, _) => args.first(), typ => unreachable!("Unexpected type for function: {typ}"), }, typ => unreachable!("Unexpected type for function: {typ}"), @@ -483,13 +541,11 @@ impl<'interner> TypeChecker<'interner> { let func_meta = self.interner.function_meta(&func_id); let param_len = func_meta.parameters.len(); - (func_meta.typ, param_len) } - HirMethodReference::TraitMethodId(_, method) => { + 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()) } }; @@ -508,7 +564,6 @@ impl<'interner> TypeChecker<'interner> { self.interner.store_instantiation_bindings(*function_ident_id, instantiation_bindings); self.interner.push_expr_type(function_ident_id, function_type.clone()); - self.bind_function_type(function_type, arguments, span) } @@ -824,7 +879,7 @@ impl<'interner> TypeChecker<'interner> { method_name: &str, expr_id: &ExprId, ) -> Option { - match object_type { + match object_type.follow_bindings() { Type::Struct(typ, _args) => { let id = typ.borrow().id; match self.interner.lookup_method(object_type, id, method_name, false) { @@ -854,16 +909,15 @@ impl<'interner> TypeChecker<'interner> { for constraint in func_meta.trait_constraints { if *object_type == constraint.typ { - let the_trait = self.interner.get_trait(constraint.trait_id); - - for (method_index, method) in the_trait.methods.iter().enumerate() { - if method.name.0.contents == method_name { - let trait_method = - TraitMethodId { trait_id: constraint.trait_id, method_index }; - return Some(HirMethodReference::TraitMethodId( - object_type.clone(), - trait_method, - )); + if let Some(the_trait) = self.interner.try_get_trait(constraint.trait_id) { + for (method_index, method) in the_trait.methods.iter().enumerate() { + if method.name.0.contents == method_name { + let trait_method = TraitMethodId { + trait_id: constraint.trait_id, + method_index, + }; + return Some(HirMethodReference::TraitMethodId(trait_method)); + } } } } @@ -880,20 +934,22 @@ impl<'interner> TypeChecker<'interner> { // This may be a struct or a primitive type. Type::MutableReference(element) => self .interner - .lookup_mut_primitive_trait_method(element.as_ref(), method_name) + .lookup_primitive_trait_method_mut(element.as_ref(), method_name) .map(HirMethodReference::FuncId) - .or_else(|| self.lookup_method(element, method_name, expr_id)), + .or_else(|| self.lookup_method(&element, method_name, expr_id)), + // If we fail to resolve the object to a struct type, we have no way of type // checking its arguments as we can't even resolve the name of the function Type::Error => None, - // In the future we could support methods for non-struct types if we have a context - // (in the interner?) essentially resembling HashMap - other => match self - .interner - .lookup_primitive_method(other, method_name) - .or_else(|| self.interner.lookup_primitive_trait_method(other, method_name)) - { + // The type variable must be unbound at this point since follow_bindings was called + Type::TypeVariable(_, TypeVariableKind::Normal) => { + let span = self.interner.expr_span(expr_id); + self.errors.push(TypeCheckError::TypeAnnotationsNeeded { span }); + None + } + + other => match self.interner.lookup_primitive_method(&other, method_name) { Some(method_id) => Some(HirMethodReference::FuncId(method_id)), None => { self.errors.push(TypeCheckError::UnresolvedMethodCall { diff --git a/compiler/noirc_frontend/src/hir/type_check/mod.rs b/compiler/noirc_frontend/src/hir/type_check/mod.rs index 035dbbc3518..19d9d370377 100644 --- a/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -14,8 +14,8 @@ mod stmt; pub use errors::TypeCheckError; use crate::{ - hir_def::{expr::HirExpression, stmt::HirStatement}, - node_interner::{ExprId, FuncId, NodeInterner, StmtId, TraitImplKey}, + hir_def::{expr::HirExpression, stmt::HirStatement, traits::TraitConstraint}, + node_interner::{ExprId, FuncId, NodeInterner, StmtId}, Type, }; @@ -28,6 +28,12 @@ pub struct TypeChecker<'interner> { interner: &'interner mut NodeInterner, errors: Vec, current_function: Option, + + /// Trait constraints are collected during type checking until they are + /// verified at the end of a function. This is because constraints arise + /// on each variable, but it is only until function calls when the types + /// needed for the trait constraint may become known. + trait_constraints: Vec<(TraitConstraint, ExprId)>, } /// Type checks a function and assigns the @@ -43,6 +49,24 @@ pub fn type_check_func(interner: &mut NodeInterner, func_id: FuncId) -> Vec Vec Vec (noirc_e impl<'interner> TypeChecker<'interner> { fn new(interner: &'interner mut NodeInterner) -> Self { - Self { delayed_type_checks: Vec::new(), interner, errors: vec![], current_function: None } + Self { + delayed_type_checks: Vec::new(), + interner, + errors: Vec::new(), + trait_constraints: Vec::new(), + current_function: None, + } } pub fn push_delayed_type_check(&mut self, f: TypeCheckFn) { self.delayed_type_checks.push(f); } - fn check_function_body( - mut self, - body: &ExprId, - ) -> (Type, Vec, Vec) { + fn check_function_body(&mut self, body: &ExprId) -> (Type, Vec) { let body_type = self.check_expression(body); - (body_type, self.delayed_type_checks, self.errors) + (body_type, std::mem::take(&mut self.delayed_type_checks)) } pub fn check_global(id: &StmtId, interner: &'interner mut NodeInterner) -> Vec { let mut this = Self { delayed_type_checks: Vec::new(), interner, - errors: vec![], + errors: Vec::new(), + trait_constraints: Vec::new(), current_function: None, }; this.check_statement(id); @@ -285,6 +325,7 @@ mod test { return_visibility: Visibility::Private, return_distinctness: Distinctness::DuplicationAllowed, has_body: true, + trait_impl: None, return_type: FunctionReturnType::Default(Span::default()), trait_constraints: Vec::new(), }; diff --git a/compiler/noirc_frontend/src/hir_def/expr.rs b/compiler/noirc_frontend/src/hir_def/expr.rs index 42803378ccb..755817ba1e6 100644 --- a/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/compiler/noirc_frontend/src/hir_def/expr.rs @@ -29,7 +29,7 @@ pub enum HirExpression { If(HirIfExpression), Tuple(Vec), Lambda(HirLambda), - TraitMethodReference(Type, TraitMethodId), + TraitMethodReference(TraitMethodId), Error, } @@ -156,7 +156,7 @@ pub enum HirMethodReference { /// Or a method can come from a Trait impl block, in which case /// the actual function called will depend on the instantiated type, /// which can be only known during monomorphization. - TraitMethodId(Type, TraitMethodId), + TraitMethodId(TraitMethodId), } impl HirMethodCallExpression { @@ -174,8 +174,8 @@ impl HirMethodCallExpression { let id = interner.function_definition_id(func_id); HirExpression::Ident(HirIdent { location, id }) } - HirMethodReference::TraitMethodId(typ, method_id) => { - HirExpression::TraitMethodReference(typ, method_id) + HirMethodReference::TraitMethodId(method_id) => { + HirExpression::TraitMethodReference(method_id) } }; let func = interner.push_expr(expr); diff --git a/compiler/noirc_frontend/src/hir_def/function.rs b/compiler/noirc_frontend/src/hir_def/function.rs index 6e4490af5de..085bda107e3 100644 --- a/compiler/noirc_frontend/src/hir_def/function.rs +++ b/compiler/noirc_frontend/src/hir_def/function.rs @@ -4,7 +4,7 @@ use noirc_errors::{Location, Span}; use super::expr::{HirBlockExpression, HirExpression, HirIdent}; use super::stmt::HirPattern; use super::traits::TraitConstraint; -use crate::node_interner::{ExprId, NodeInterner}; +use crate::node_interner::{ExprId, NodeInterner, TraitImplId}; use crate::FunctionKind; use crate::{Distinctness, FunctionReturnType, Type, Visibility}; @@ -114,6 +114,9 @@ pub struct FuncMeta { pub has_body: bool, pub trait_constraints: Vec, + + /// The trait impl this function belongs to, if any + pub trait_impl: Option, } impl FuncMeta { diff --git a/compiler/noirc_frontend/src/hir_def/traits.rs b/compiler/noirc_frontend/src/hir_def/traits.rs index 3f01df4426a..062f505c179 100644 --- a/compiler/noirc_frontend/src/hir_def/traits.rs +++ b/compiler/noirc_frontend/src/hir_def/traits.rs @@ -1,14 +1,17 @@ +use std::rc::Rc; + use crate::{ graph::CrateId, node_interner::{FuncId, TraitId, TraitMethodId}, Generics, Ident, NoirFunction, Type, TypeVariable, TypeVariableId, }; +use fm::FileId; use noirc_errors::Span; #[derive(Clone, Debug, PartialEq, Eq)] pub struct TraitFunction { pub name: Ident, - pub generics: Generics, + pub generics: Vec<(Rc, TypeVariable, Span)>, pub arguments: Vec, pub return_type: Type, pub span: Span, @@ -62,7 +65,14 @@ pub struct TraitImpl { pub ident: Ident, pub typ: Type, pub trait_id: TraitId, + pub file: FileId, pub methods: Vec, // methods[i] is the implementation of trait.methods[i] for Type typ + + /// The where clause, if present, contains each trait requirement which must + /// be satisfied for this impl to be selected. E.g. in `impl Eq for [T] where T: Eq`, + /// `where_clause` would contain the one `T: Eq` constraint. If there is no where clause, + /// this Vec is empty. + pub where_clause: Vec, } #[derive(Debug, Clone)] @@ -72,6 +82,12 @@ pub struct TraitConstraint { // pub trait_generics: Generics, TODO } +impl TraitConstraint { + pub fn new(typ: Type, trait_id: TraitId) -> Self { + Self { typ, trait_id } + } +} + impl std::hash::Hash for Trait { fn hash(&self, state: &mut H) { self.id.hash(state); @@ -135,5 +151,6 @@ impl TraitFunction { Box::new(self.return_type.clone()), Box::new(Type::Unit), ) + .generalize() } } diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index 110334f331e..46818626a16 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -103,6 +103,47 @@ pub enum Type { Error, } +impl Type { + /// Returns the number of field elements required to represent the type once encoded. + pub fn field_count(&self) -> u32 { + match self { + Type::FieldElement | Type::Integer { .. } | Type::Bool => 1, + Type::Array(size, typ) => { + let length = size + .evaluate_to_u64() + .expect("Cannot have variable sized arrays as a parameter to main"); + let typ = typ.as_ref(); + (length as u32) * typ.field_count() + } + Type::Struct(ref def, args) => { + let struct_type = def.borrow(); + let fields = struct_type.get_fields(args); + fields.iter().fold(0, |acc, (_, field_type)| acc + field_type.field_count()) + } + Type::Tuple(fields) => { + fields.iter().fold(0, |acc, field_typ| acc + field_typ.field_count()) + } + Type::String(size) => { + let size = size + .evaluate_to_u64() + .expect("Cannot have variable sized strings as a parameter to main"); + size as u32 + } + Type::FmtString(_, _) + | Type::Unit + | Type::TypeVariable(_, _) + | Type::TraitAsType(_) + | Type::NamedGeneric(_, _) + | Type::Function(_, _, _) + | Type::MutableReference(_) + | Type::Forall(_, _) + | Type::Constant(_) + | Type::NotConstant + | Type::Error => unreachable!("This type cannot exist as a parameter to main"), + } + } +} + /// A list of TypeVariableIds to bind to a type. Storing the /// TypeVariable in addition to the matching TypeVariableId allows /// the binding to later be undone if needed. @@ -560,6 +601,47 @@ impl Type { .all(|(_, field)| field.is_valid_for_program_input()), } } + + /// Returns the number of `Forall`-quantified type variables on this type. + /// Returns 0 if this is not a Type::Forall + pub fn generic_count(&self) -> usize { + match self { + Type::Forall(generics, _) => generics.len(), + Type::TypeVariable(type_variable, _) | Type::NamedGeneric(type_variable, _) => { + match &*type_variable.borrow() { + TypeBinding::Bound(binding) => binding.generic_count(), + TypeBinding::Unbound(_) => 0, + } + } + _ => 0, + } + } + + /// 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 { @@ -911,8 +993,24 @@ 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) + } else { + unreachable!("If guard ensures binding is bound") + } + } + (NamedGeneric(binding_a, name_a), NamedGeneric(binding_b, name_b)) => { - // Ensure NamedGenerics are never bound during type checking + // Unbound NamedGenerics are caught by the checks above assert!(binding_a.borrow().is_unbound()); assert!(binding_b.borrow().is_unbound()); @@ -1069,6 +1167,82 @@ impl Type { } } + /// Replace each NamedGeneric (and TypeVariable) in this type with a fresh type variable + pub(crate) fn instantiate_type_variables( + &self, + interner: &NodeInterner, + ) -> (Type, TypeBindings) { + let mut type_variables = HashMap::new(); + self.find_all_unbound_type_variables(&mut type_variables); + + let substitutions = type_variables + .into_iter() + .map(|(id, type_var)| (id, (type_var, interner.next_type_variable()))) + .collect(); + + (self.substitute(&substitutions), substitutions) + } + + /// For each unbound type variable in the current type, add a type binding to the given list + /// to bind the unbound type variable to a fresh type variable. + fn find_all_unbound_type_variables( + &self, + type_variables: &mut HashMap, + ) { + match self { + Type::FieldElement + | Type::Integer(_, _) + | Type::Bool + | Type::Unit + | Type::TraitAsType(_) + | Type::Constant(_) + | Type::NotConstant + | Type::Error => (), + Type::Array(length, elem) => { + length.find_all_unbound_type_variables(type_variables); + elem.find_all_unbound_type_variables(type_variables); + } + Type::String(length) => length.find_all_unbound_type_variables(type_variables), + Type::FmtString(length, env) => { + length.find_all_unbound_type_variables(type_variables); + env.find_all_unbound_type_variables(type_variables); + } + Type::Struct(_, generics) => { + for generic in generics { + generic.find_all_unbound_type_variables(type_variables); + } + } + Type::Tuple(fields) => { + for field in fields { + field.find_all_unbound_type_variables(type_variables); + } + } + Type::Function(args, ret, env) => { + for arg in args { + arg.find_all_unbound_type_variables(type_variables); + } + ret.find_all_unbound_type_variables(type_variables); + env.find_all_unbound_type_variables(type_variables); + } + Type::MutableReference(elem) => { + elem.find_all_unbound_type_variables(type_variables); + } + Type::Forall(_, typ) => typ.find_all_unbound_type_variables(type_variables), + Type::TypeVariable(type_variable, _) | Type::NamedGeneric(type_variable, _) => { + match &*type_variable.borrow() { + TypeBinding::Bound(binding) => { + binding.find_all_unbound_type_variables(type_variables); + } + TypeBinding::Unbound(id) => { + if !type_variables.contains_key(id) { + type_variables.insert(*id, type_variable.clone()); + } + } + } + } + } + } + /// Substitute any type variables found within this type with the /// given bindings if found. If a type variable is not found within /// the given TypeBindings, it is unchanged. diff --git a/compiler/noirc_frontend/src/lexer/lexer.rs b/compiler/noirc_frontend/src/lexer/lexer.rs index 2576b7a08ab..be24c1249c6 100644 --- a/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/compiler/noirc_frontend/src/lexer/lexer.rs @@ -6,20 +6,17 @@ use super::{ }; use acvm::FieldElement; use noirc_errors::{Position, Span}; -use std::str::Chars; -use std::{ - iter::{Peekable, Zip}, - ops::RangeFrom, -}; +use std::str::CharIndices; /// The job of the lexer is to transform an iterator of characters (`char_iter`) /// into an iterator of `SpannedToken`. Each `Token` corresponds roughly to 1 word or operator. /// Tokens are tagged with their location in the source file (a `Span`) for use in error reporting. pub struct Lexer<'a> { - char_iter: Peekable, RangeFrom>>, + chars: CharIndices<'a>, position: Position, done: bool, skip_comments: bool, + skip_whitespaces: bool, } pub type SpannedTokenResult = Result; @@ -42,11 +39,11 @@ impl<'a> Lexer<'a> { pub fn new(source: &'a str) -> Self { Lexer { - // We zip with the character index here to ensure the first char has index 0 - char_iter: source.chars().zip(0..).peekable(), + chars: source.char_indices(), position: 0, done: false, skip_comments: true, + skip_whitespaces: true, } } @@ -55,23 +52,28 @@ impl<'a> Lexer<'a> { self } + pub fn skip_whitespaces(mut self, flag: bool) -> Self { + self.skip_whitespaces = flag; + self + } + /// Iterates the cursor and returns the char at the new cursor position fn next_char(&mut self) -> Option { - let (c, index) = self.char_iter.next()?; - self.position = index; - Some(c) + let (position, ch) = self.chars.next()?; + self.position = position as u32; + Some(ch) } /// Peeks at the next char. Does not iterate the cursor fn peek_char(&mut self) -> Option { - self.char_iter.peek().map(|(c, _)| *c) + self.chars.clone().next().map(|(_, ch)| ch) } /// Peeks at the character two positions ahead. Does not iterate the cursor fn peek2_char(&mut self) -> Option { - let mut chars = self.char_iter.clone(); + let mut chars = self.chars.clone(); chars.next(); - chars.next().map(|(c, _)| c) + chars.next().map(|(_, ch)| ch) } /// Peeks at the next char and returns true if it is equal to the char argument @@ -92,9 +94,13 @@ impl<'a> Lexer<'a> { fn next_token(&mut self) -> SpannedTokenResult { match self.next_char() { - Some(x) if { x.is_whitespace() } => { - self.eat_whitespace(); - self.next_token() + Some(x) if x.is_whitespace() => { + let spanned = self.eat_whitespace(x); + if self.skip_whitespaces { + self.next_token() + } else { + Ok(spanned) + } } Some('<') => self.glue(Token::Less), Some('>') => self.glue(Token::Greater), @@ -464,8 +470,10 @@ impl<'a> Lexer<'a> { } /// Skips white space. They are not significant in the source language - fn eat_whitespace(&mut self) { - self.eat_while(None, |ch| ch.is_whitespace()); + fn eat_whitespace(&mut self, initial_char: char) -> SpannedToken { + let start = self.position; + let whitespace = self.eat_while(initial_char.into(), |ch| ch.is_whitespace()); + SpannedToken::new(Token::Whitespace(whitespace), Span::inclusive(start, self.position)) } } @@ -551,6 +559,20 @@ mod tests { ); } + #[test] + fn test_attribute_with_apostrophe() { + let input = r#"#[test(should_fail_with = "the eagle's feathers")]"#; + 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() } + ))) + ); + } + #[test] fn deprecated_attribute_with_note() { let input = r#"#[deprecated("hello")]"#; diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index fe3e9476318..72be71865cc 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -88,6 +88,8 @@ pub enum Token { #[allow(clippy::upper_case_acronyms)] EOF, + Whitespace(String), + /// An invalid character is one that is not in noir's language or grammar. /// /// We don't report invalid tokens in the source as errors until parsing to @@ -194,6 +196,7 @@ impl fmt::Display for Token { Token::Bang => write!(f, "!"), Token::EOF => write!(f, "end of input"), Token::Invalid(c) => write!(f, "{c}"), + Token::Whitespace(ref s) => write!(f, "{s}"), } } } @@ -462,6 +465,7 @@ impl Attribute { || ch == '=' || ch == '"' || ch == ' ' + || ch == '\'' }) .then_some(()); diff --git a/compiler/noirc_frontend/src/monomorphization/mod.rs b/compiler/noirc_frontend/src/monomorphization/mod.rs index 6891bcf2872..57e4e6cdeb0 100644 --- a/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -24,7 +24,7 @@ use crate::{ stmt::{HirAssignStatement, HirLValue, HirLetStatement, HirPattern, HirStatement}, types, }, - node_interner::{self, DefinitionKind, NodeInterner, StmtId, TraitImplKey, TraitMethodId}, + node_interner::{self, DefinitionKind, NodeInterner, StmtId, TraitImplKind, TraitMethodId}, token::FunctionAttribute, ContractFunctionType, FunctionKind, Type, TypeBinding, TypeBindings, TypeVariableKind, Visibility, @@ -378,9 +378,9 @@ impl<'interner> Monomorphizer<'interner> { HirExpression::Lambda(lambda) => self.lambda(lambda, expr), - HirExpression::TraitMethodReference(typ, method) => { + HirExpression::TraitMethodReference(method) => { if let Type::Function(_, _, _) = self.interner.id_type(expr) { - self.resolve_trait_method_reference(typ, expr, method) + self.resolve_trait_method_reference(expr, method) } else { unreachable!( "Calling a non-function, this should've been caught in typechecking" @@ -812,7 +812,6 @@ impl<'interner> Monomorphizer<'interner> { fn resolve_trait_method_reference( &mut self, - self_type: HirType, expr_id: node_interner::ExprId, method: TraitMethodId, ) -> ast::Expression { @@ -820,13 +819,36 @@ impl<'interner> Monomorphizer<'interner> { let trait_impl = self .interner - .get_trait_implementation(&TraitImplKey { - typ: self_type.follow_bindings(), - trait_id: method.trait_id, - }) + .get_selected_impl_for_ident(expr_id) .expect("ICE: missing trait impl - should be caught during type checking"); - let hir_func_id = trait_impl.borrow().methods[method.method_index]; + let hir_func_id = match trait_impl { + node_interner::TraitImplKind::Normal(impl_id) => { + self.interner.get_trait_implementation(impl_id).borrow().methods + [method.method_index] + } + node_interner::TraitImplKind::Assumed { object_type } => { + match self.interner.lookup_trait_implementation(&object_type, method.trait_id) { + Ok(TraitImplKind::Normal(impl_id)) => { + self.interner.get_trait_implementation(impl_id).borrow().methods + [method.method_index] + } + Ok(TraitImplKind::Assumed { .. }) => unreachable!( + "There should be no remaining Assumed impls during monomorphization" + ), + Err(constraints) => { + let failed_constraints = vecmap(constraints, |constraint| { + let id = constraint.trait_id; + let name = self.interner.get_trait(id).name.to_string(); + format!(" {}: {name}", constraint.typ) + }) + .join("\n"); + + unreachable!("Failed to find trait impl during monomorphization. The failed constraint(s) are:\n{failed_constraints}") + } + } + } + }; let func_def = self.lookup_function(hir_func_id, expr_id, &function_type); let func_id = match func_def { diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 514a65d37a2..300a95f819c 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -11,8 +11,8 @@ use crate::hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait, Unr use crate::hir::def_map::{LocalModuleId, ModuleId}; use crate::hir::StorageSlot; use crate::hir_def::stmt::HirLetStatement; -use crate::hir_def::traits::Trait; use crate::hir_def::traits::TraitImpl; +use crate::hir_def::traits::{Trait, TraitConstraint}; use crate::hir_def::types::{StructType, Type}; use crate::hir_def::{ expr::HirExpression, @@ -25,12 +25,9 @@ use crate::{ TypeBinding, TypeBindings, TypeVariable, TypeVariableId, TypeVariableKind, }; -#[derive(Eq, PartialEq, Hash, Clone)] -pub struct TraitImplKey { - pub typ: Type, - pub trait_id: TraitId, - // pub generics: Generics - TODO -} +/// An arbitrary number to limit the recursion depth when searching for trait impls. +/// This is needed to stop recursing for cases such as `impl Foo for T where T: Eq` +const IMPL_SEARCH_RECURSION_LIMIT: u32 = 10; type StructAttributes = Vec; @@ -92,7 +89,25 @@ pub struct NodeInterner { // Trait implementation map // For each type that implements a given Trait ( corresponding TraitId), there should be an entry here // The purpose for this hashmap is to detect duplication of trait implementations ( if any ) - trait_implementations: HashMap>, + // + // Indexed by TraitImplIds + trait_implementations: Vec>, + + /// Trait implementations on each type. This is expected to always have the same length as + /// `self.trait_implementations`. + /// + /// For lack of a better name, this maps a trait id and type combination + /// to a corresponding impl if one is available for the type. Due to generics, + /// we cannot map from Type directly to impl, we need to iterate a Vec of all impls + /// of that trait to see if any type may match. This can be further optimized later + /// by splitting it up by type. + trait_implementation_map: HashMap>, + + /// When impls are found during type checking, we tag the function call's Ident + /// with the impl that was selected. For cases with where clauses, this may be + /// an Assumed (but verified) impl. In this case the monomorphizer should have + /// the context to get the concrete type of the object and select the correct impl itself. + selected_trait_implementations: HashMap, /// Map from ExprId (referring to a Function/Method call) to its corresponding TypeBindings, /// filled out during type checking from instantiated variables. Used during monomorphization @@ -113,16 +128,39 @@ pub struct NodeInterner { /// may have both `impl Struct { fn foo(){} }` and `impl Struct { fn foo(){} }`. /// If this happens, the returned Vec will have 2 entries and we'll need to further /// disambiguate them by checking the type of each function. - struct_methods: HashMap<(StructId, String), Vec>, + struct_methods: HashMap<(StructId, String), Methods>, /// Methods on primitive types defined in the stdlib. - primitive_methods: HashMap<(TypeMethodKey, String), FuncId>, + primitive_methods: HashMap<(TypeMethodKey, String), Methods>, // For trait implementation functions, this is their self type and trait they belong to func_id_to_trait: HashMap, +} - /// Trait implementations on primitive types - primitive_trait_impls: HashMap<(Type, String), FuncId>, +/// A trait implementation is either a normal implementation that is present in the source +/// program via an `impl` block, or it is assumed to exist from a `where` clause or similar. +#[derive(Debug, Clone)] +pub enum TraitImplKind { + Normal(TraitImplId), + + /// Assumed impls don't have an impl id since they don't link back to any concrete part of the source code. + Assumed { + object_type: Type, + }, +} + +/// Represents the methods on a given type that each share the same name. +/// +/// Methods are split into inherent methods and trait methods. If there is +/// ever a name that is defined on both a type directly, and defined indirectly +/// via a trait impl, the direct (inherent) name will always take precedence. +/// +/// 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)] +pub struct Methods { + direct: Vec, + trait_impl_methods: Vec, } /// All the information from a function that is filled out during definition collection rather than @@ -257,6 +295,9 @@ impl TraitId { } } +#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)] +pub struct TraitImplId(usize); + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct TraitMethodId { pub trait_id: TraitId, @@ -380,14 +421,15 @@ impl Default for NodeInterner { struct_attributes: HashMap::new(), type_aliases: Vec::new(), traits: HashMap::new(), - trait_implementations: HashMap::new(), + trait_implementations: Vec::new(), + trait_implementation_map: HashMap::new(), + selected_trait_implementations: HashMap::new(), instantiation_bindings: HashMap::new(), field_indices: HashMap::new(), next_type_variable_id: std::cell::Cell::new(0), globals: HashMap::new(), struct_methods: HashMap::new(), primitive_methods: HashMap::new(), - primitive_trait_impls: HashMap::new(), }; // An empty block expression is used often, we add this into the `node` on startup @@ -618,9 +660,10 @@ impl NodeInterner { #[cfg(test)] pub fn push_test_function_definition(&mut self, name: String) -> FuncId { let id = self.push_fn(HirFunction::empty()); - let modifiers = FunctionModifiers::new(); + let mut modifiers = FunctionModifiers::new(); + modifiers.name = name; let module = ModuleId::dummy_id(); - self.push_function_definition(name, id, modifiers, module); + self.push_function_definition(id, modifiers, module); id } @@ -631,7 +674,6 @@ impl NodeInterner { module: ModuleId, ) -> DefinitionId { use ContractFunctionType::*; - let name = function.name.0.contents.clone(); // We're filling in contract_function_type and is_internal now, but these will be verified // later during name resolution. @@ -643,16 +685,16 @@ impl NodeInterner { contract_function_type: Some(if function.is_open { Open } else { Secret }), is_internal: Some(function.is_internal), }; - self.push_function_definition(name, id, modifiers, module) + self.push_function_definition(id, modifiers, module) } pub fn push_function_definition( &mut self, - name: String, func: FuncId, modifiers: FunctionModifiers, module: ModuleId, ) -> 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)) @@ -803,6 +845,10 @@ impl NodeInterner { self.traits[&id].clone() } + pub fn try_get_trait(&self, id: TraitId) -> Option { + self.traits.get(&id).cloned() + } + pub fn get_type_alias(&self, id: TypeAliasId) -> &TypeAliasType { &self.type_aliases[id.0] } @@ -891,6 +937,7 @@ impl NodeInterner { self_type: &Type, method_name: String, method_id: FuncId, + is_trait_method: bool, ) -> Option { match self_type { Type::Struct(struct_type, _generics) => { @@ -901,68 +948,166 @@ impl NodeInterner { } let key = (id, method_name); - self.struct_methods.entry(key).or_default().push(method_id); + self.struct_methods.entry(key).or_default().add_method(method_id, is_trait_method); None } Type::Error => None, + Type::MutableReference(element) => { + self.add_method(element, method_name, method_id, is_trait_method) + } other => { let key = get_type_method_key(self_type).unwrap_or_else(|| { unreachable!("Cannot add a method to the unsupported type '{}'", other) }); - self.primitive_methods.insert((key, method_name), method_id) + self.primitive_methods + .entry((key, method_name)) + .or_default() + .add_method(method_id, is_trait_method); + None + } + } + } + + pub fn get_trait_implementation(&self, id: TraitImplId) -> Shared { + self.trait_implementations[id.0].clone() + } + + /// Given a `ObjectType: TraitId` pair, try to find an existing impl that satisfies the + /// constraint. If an impl cannot be found, this will return a vector of each constraint + /// in the path to get to the failing constraint. Usually this is just the single failing + /// constraint, but when where clauses are involved, the failing constraint may be several + /// constraints deep. In this case, all of the constraints are returned, starting with the + /// failing one. + pub fn lookup_trait_implementation( + &self, + object_type: &Type, + trait_id: TraitId, + ) -> Result> { + self.lookup_trait_implementation_helper(object_type, trait_id, IMPL_SEARCH_RECURSION_LIMIT) + } + + fn lookup_trait_implementation_helper( + &self, + object_type: &Type, + trait_id: TraitId, + recursion_limit: u32, + ) -> Result> { + let make_constraint = || TraitConstraint::new(object_type.clone(), trait_id); + + // Prevent infinite recursion when looking for impls + if recursion_limit == 0 { + return Err(vec![make_constraint()]); + } + + 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); + + 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, + recursion_limit, + ) { + errors.push(make_constraint()); + return Err(errors); + } + } + + return Ok(impl_kind.clone()); } } + + Err(vec![make_constraint()]) + } + + /// Verifies that each constraint in the given where clause is valid. + /// If an impl cannot be found for any constraint, the erroring constraint is returned. + fn validate_where_clause( + &self, + where_clause: &[TraitConstraint], + type_bindings: &TypeBindings, + recursion_limit: u32, + ) -> Result<(), Vec> { + for constraint in where_clause { + let constraint_type = constraint.typ.substitute(type_bindings); + self.lookup_trait_implementation_helper( + &constraint_type, + constraint.trait_id, + recursion_limit - 1, + )?; + } + Ok(()) } - pub fn get_trait_implementation(&self, key: &TraitImplKey) -> Option> { - self.trait_implementations.get(key).cloned() + /// Adds an "assumed" trait implementation to the currently known trait implementations. + /// Unlike normal trait implementations, these are only assumed to exist. They often correspond + /// to `where` clauses in functions where we assume there is some `T: Eq` even though we do + /// not yet know T. For these cases, we store an impl here so that we assume they exist and + /// can resolve them. They are then later verified when the function is called, and linked + /// properly after being monomorphized to the correct variant. + /// + /// Returns true on success, or false if there is already an overlapping impl in scope. + pub fn add_assumed_trait_implementation( + &mut self, + object_type: Type, + trait_id: TraitId, + ) -> bool { + // Make sure there are no overlapping impls + if self.lookup_trait_implementation(&object_type, trait_id).is_ok() { + return false; + } + + let entries = self.trait_implementation_map.entry(trait_id).or_default(); + entries.push((object_type.clone(), TraitImplKind::Assumed { object_type })); + true } + /// Adds a trait implementation to the list of known implementations. pub fn add_trait_implementation( &mut self, - key: &TraitImplKey, + object_type: Type, + trait_id: TraitId, + impl_id: TraitImplId, trait_impl: Shared, - ) -> bool { - self.trait_implementations.insert(key.clone(), trait_impl.clone()); - match &key.typ { - Type::Struct(..) => { - for func_id in &trait_impl.borrow().methods { - let method_name = self.function_name(func_id).to_owned(); - self.add_method(&key.typ, method_name, *func_id); - } - true - } - Type::FieldElement - | Type::Unit - | Type::Array(..) - | Type::Integer(..) - | Type::Bool - | Type::Tuple(..) - | Type::String(..) - | Type::FmtString(..) - | Type::Function(..) - | Type::MutableReference(..) => { - for func_id in &trait_impl.borrow().methods { - let method_name = self.function_name(func_id).to_owned(); - let key = (key.typ.clone(), method_name); - self.primitive_trait_impls.insert(key, *func_id); - } - true - } - // We should allow implementing traits NamedGenerics will also eventually be possible once we support generics - // impl Foo for T - // but it's fine not to include these until we do. - Type::NamedGeneric(..) => false, - // prohibited are internal types (like NotConstant, TypeVariable, Forall, and Error) that - // aren't possible for users to write anyway - Type::TypeVariable(..) - | Type::Forall(..) - | Type::NotConstant - | Type::Constant(..) - | Type::TraitAsType(..) - | Type::Error => false, + ) -> Result<(), (Span, FileId)> { + assert_eq!(impl_id.0, self.trait_implementations.len(), "trait impl defined out of order"); + + self.trait_implementations.push(trait_impl.clone()); + + // Ignoring overlapping TraitImplKind::Assumed impls here is perfectly fine. + // It should never happen since impls are defined at global scope, but even + // if they were, we should never prevent defining a new impl because a where + // clause already assumes it exists. + 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) + { + let existing_impl = self.get_trait_implementation(existing); + let existing_impl = existing_impl.borrow(); + return Err((existing_impl.ident.span(), existing_impl.file)); + } + + for method in &trait_impl.borrow().methods { + let method_name = self.function_name(method).to_owned(); + self.add_method(&object_type, method_name, *method, true); } + + // The object type is generalized so that a generic impl will apply + // to any type T, rather than just the generic type named T. + let generalized_object_type = object_type.generalize_from_substitutions(substitutions); + let entries = self.trait_implementation_map.entry(trait_id).or_default(); + entries.push((generalized_object_type, TraitImplKind::Normal(impl_id))); + Ok(()) } /// Search by name for a method on the given struct. @@ -981,25 +1126,121 @@ impl NodeInterner { typ: &Type, id: StructId, method_name: &str, - check_type: bool, + force_type_check: bool, ) -> Option { let methods = self.struct_methods.get(&(id, method_name.to_owned()))?; // If there is only one method, just return it immediately. // It will still be typechecked later. - if !check_type && methods.len() == 1 { - return Some(methods[0]); + if !force_type_check { + if let Some(method) = methods.get_unambiguous() { + return Some(method); + } } + self.find_matching_method(typ, methods, method_name) + } + + /// Select the 1 matching method with an object type matching `typ` + fn find_matching_method( + &self, + typ: &Type, + methods: &Methods, + method_name: &str, + ) -> Option { + if let Some(method) = methods.find_matching_method(typ, self) { + Some(method) + } else { + // Failed to find a match for the type in question, switch to looking at impls + // for all types `T`, e.g. `impl Foo for T` + let key = &(TypeMethodKey::Generic, method_name.to_owned()); + let global_methods = self.primitive_methods.get(key)?; + global_methods.find_matching_method(typ, self) + } + } + + /// Looks up a given method name on the given primitive type. + pub fn lookup_primitive_method(&self, typ: &Type, method_name: &str) -> Option { + let key = get_type_method_key(typ)?; + let methods = self.primitive_methods.get(&(key, method_name.to_owned()))?; + self.find_matching_method(typ, methods, method_name) + } + + pub fn lookup_primitive_trait_method_mut( + &self, + typ: &Type, + method_name: &str, + ) -> Option { + let typ = Type::MutableReference(Box::new(typ.clone())); + self.lookup_primitive_method(&typ, method_name) + } + + /// Returns what the next trait impl id is expected to be. + /// Note that this does not actually reserve the slot so care should + /// be taken that the next trait impl added matches this ID. + pub fn next_trait_impl_id(&self) -> TraitImplId { + TraitImplId(self.trait_implementations.len()) + } + + /// Removes all TraitImplKind::Assumed from the list of known impls for the given trait + pub fn remove_assumed_trait_implementations_for_trait(&mut self, trait_id: TraitId) { + let entries = self.trait_implementation_map.entry(trait_id).or_default(); + entries.retain(|(_, kind)| matches!(kind, TraitImplKind::Normal(_))); + } + + /// 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 impl to select (because the impl was Assumed). + pub fn select_impl_for_ident(&mut self, ident_id: ExprId, trait_impl: TraitImplKind) { + 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). + pub fn get_selected_impl_for_ident(&self, ident_id: ExprId) -> Option { + self.selected_trait_implementations.get(&ident_id).cloned() + } +} + +impl Methods { + /// Get a single, unambiguous reference to a name if one exists. + /// If not, there may be multiple methods of the same name for a given + /// type or there may be no methods at all. + fn get_unambiguous(&self) -> Option { + if self.direct.len() == 1 { + Some(self.direct[0]) + } else if self.direct.is_empty() && self.trait_impl_methods.len() == 1 { + Some(self.trait_impl_methods[0]) + } else { + None + } + } + + fn add_method(&mut self, method: FuncId, is_trait_method: bool) { + if is_trait_method { + self.trait_impl_methods.push(method); + } else { + self.direct.push(method); + } + } + + /// Iterate through each method, starting with the direct methods + fn iter(&self) -> impl Iterator + '_ { + self.direct.iter().copied().chain(self.trait_impl_methods.iter().copied()) + } + + /// Select the 1 matching method with an object type matching `typ` + fn find_matching_method(&self, typ: &Type, interner: &NodeInterner) -> Option { // When adding methods we always check they do not overlap, so there should be // at most 1 matching method in this list. - for method in methods { - match self.function_meta(method).typ.instantiate(self).0 { + for method in self.iter() { + 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() { - return Some(*method); + return Some(method); } } } @@ -1007,29 +1248,8 @@ impl NodeInterner { other => unreachable!("Expected function type, found {other}"), } } - None } - - /// Looks up a given method name on the given primitive type. - pub fn lookup_primitive_method(&self, typ: &Type, method_name: &str) -> Option { - get_type_method_key(typ) - .and_then(|key| self.primitive_methods.get(&(key, method_name.to_owned())).copied()) - } - - pub fn lookup_primitive_trait_method(&self, typ: &Type, method_name: &str) -> Option { - self.primitive_trait_impls.get(&(typ.clone(), method_name.to_string())).copied() - } - - pub fn lookup_mut_primitive_trait_method( - &self, - typ: &Type, - method_name: &str, - ) -> Option { - self.primitive_trait_impls - .get(&(Type::MutableReference(Box::new(typ.clone())), method_name.to_string())) - .copied() - } } /// These are the primitive type variants that we support adding methods to @@ -1041,9 +1261,11 @@ enum TypeMethodKey { Array, Bool, String, + FmtString, Unit, Tuple, Function, + Generic, } fn get_type_method_key(typ: &Type) -> Option { @@ -1056,20 +1278,20 @@ fn get_type_method_key(typ: &Type) -> Option { Type::TypeVariable(_, TypeVariableKind::IntegerOrField) => Some(FieldOrInt), Type::Bool => Some(Bool), Type::String(_) => Some(String), + Type::FmtString(_, _) => Some(FmtString), Type::Unit => Some(Unit), Type::Tuple(_) => Some(Tuple), Type::Function(_, _, _) => Some(Function), + Type::NamedGeneric(_, _) => Some(Generic), Type::MutableReference(element) => get_type_method_key(element), // We do not support adding methods to these types Type::TypeVariable(_, _) - | Type::NamedGeneric(_, _) | Type::Forall(_, _) | Type::Constant(_) | Type::Error | Type::NotConstant | Type::Struct(_, _) - | Type::TraitAsType(_) - | Type::FmtString(_, _) => None, + | Type::TraitAsType(_) => None, } } diff --git a/compiler/noirc_frontend/src/parser/errors.rs b/compiler/noirc_frontend/src/parser/errors.rs index b9b11d8c99e..09dc6dfff8d 100644 --- a/compiler/noirc_frontend/src/parser/errors.rs +++ b/compiler/noirc_frontend/src/parser/errors.rs @@ -30,8 +30,6 @@ pub enum ParserErrorReason { ComptimeDeprecated, #[error("{0} are experimental and aren't fully supported yet")] ExperimentalFeature(&'static str), - #[error("Where clauses are allowed only on functions with generic parameters")] - WhereClauseOnNonGenericFunction, #[error( "Multiple primary attributes found. Only one function attribute is allowed per function" )] @@ -99,6 +97,10 @@ impl ParserError { pub fn reason(&self) -> Option<&ParserErrorReason> { self.reason.as_ref() } + + pub fn is_warning(&self) -> bool { + matches!(self.reason(), Some(ParserErrorReason::ExperimentalFeature(_))) + } } impl std::fmt::Display for ParserError { diff --git a/compiler/noirc_frontend/src/parser/mod.rs b/compiler/noirc_frontend/src/parser/mod.rs index 4b76e2020b5..a6c631895cd 100644 --- a/compiler/noirc_frontend/src/parser/mod.rs +++ b/compiler/noirc_frontend/src/parser/mod.rs @@ -11,17 +11,13 @@ mod labels; #[allow(clippy::module_inception)] mod parser; -use std::sync::atomic::{AtomicU32, Ordering}; - use crate::token::{Keyword, Token}; use crate::{ast::ImportStatement, Expression, NoirStruct}; use crate::{ - BlockExpression, ExpressionKind, ForLoopStatement, Ident, IndexExpression, LetStatement, - MethodCallExpression, NoirFunction, NoirTrait, NoirTraitImpl, NoirTypeAlias, Path, PathKind, - Pattern, Recoverable, Statement, StatementKind, TypeImpl, UnresolvedType, UseTree, + Ident, LetStatement, NoirFunction, NoirTrait, NoirTraitImpl, NoirTypeAlias, Recoverable, + StatementKind, TypeImpl, UseTree, }; -use acvm::FieldElement; use chumsky::prelude::*; use chumsky::primitive::Container; pub use errors::ParserError; @@ -29,11 +25,6 @@ pub use errors::ParserErrorReason; use noirc_errors::Span; pub use parser::parse_program; -/// Counter used to generate unique names when desugaring -/// code in the parser requires the creation of fresh variables. -/// The parser is stateless so this is a static global instead. -static UNIQUE_NAME_COUNTER: AtomicU32 = AtomicU32::new(0); - #[derive(Debug, Clone)] pub(crate) enum TopLevelStatement { Function(NoirFunction), @@ -478,106 +469,6 @@ impl Precedence { } } -enum ForRange { - Range(/*start:*/ Expression, /*end:*/ Expression), - Array(Expression), -} - -impl ForRange { - /// Create a 'for' expression taking care of desugaring a 'for e in array' loop - /// into the following if needed: - /// - /// { - /// let fresh1 = array; - /// for fresh2 in 0 .. std::array::len(fresh1) { - /// let elem = fresh1[fresh2]; - /// ... - /// } - /// } - fn into_for(self, identifier: Ident, block: Expression, for_loop_span: Span) -> StatementKind { - match self { - ForRange::Range(start_range, end_range) => { - StatementKind::For(ForLoopStatement { identifier, start_range, end_range, block }) - } - ForRange::Array(array) => { - let array_span = array.span; - let start_range = ExpressionKind::integer(FieldElement::zero()); - let start_range = Expression::new(start_range, array_span); - - let next_unique_id = UNIQUE_NAME_COUNTER.fetch_add(1, Ordering::Relaxed); - let array_name = format!("$i{next_unique_id}"); - let array_span = array.span; - let array_ident = Ident::new(array_name, array_span); - - // let fresh1 = array; - let let_array = Statement { - kind: StatementKind::Let(LetStatement { - pattern: Pattern::Identifier(array_ident.clone()), - r#type: UnresolvedType::unspecified(), - expression: array, - }), - span: array_span, - }; - - // array.len() - let segments = vec![array_ident]; - let array_ident = - ExpressionKind::Variable(Path { segments, kind: PathKind::Plain }); - - let end_range = ExpressionKind::MethodCall(Box::new(MethodCallExpression { - object: Expression::new(array_ident.clone(), array_span), - method_name: Ident::new("len".to_string(), array_span), - arguments: vec![], - })); - let end_range = Expression::new(end_range, array_span); - - let next_unique_id = UNIQUE_NAME_COUNTER.fetch_add(1, Ordering::Relaxed); - let index_name = format!("$i{next_unique_id}"); - let fresh_identifier = Ident::new(index_name.clone(), array_span); - - // array[i] - let segments = vec![Ident::new(index_name, array_span)]; - let index_ident = - ExpressionKind::Variable(Path { segments, kind: PathKind::Plain }); - - let loop_element = ExpressionKind::Index(Box::new(IndexExpression { - collection: Expression::new(array_ident, array_span), - index: Expression::new(index_ident, array_span), - })); - - // let elem = array[i]; - let let_elem = Statement { - kind: StatementKind::Let(LetStatement { - pattern: Pattern::Identifier(identifier), - r#type: UnresolvedType::unspecified(), - expression: Expression::new(loop_element, array_span), - }), - span: array_span, - }; - - let block_span = block.span; - let new_block = BlockExpression(vec![ - let_elem, - Statement { kind: StatementKind::Expression(block), span: block_span }, - ]); - let new_block = Expression::new(ExpressionKind::Block(new_block), block_span); - let for_loop = Statement { - kind: StatementKind::For(ForLoopStatement { - identifier: fresh_identifier, - start_range, - end_range, - block: new_block, - }), - span: for_loop_span, - }; - - let block = ExpressionKind::Block(BlockExpression(vec![let_array, for_loop])); - StatementKind::Expression(Expression::new(block, for_loop_span)) - } - } - } -} - impl std::fmt::Display for TopLevelStatement { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { diff --git a/compiler/noirc_frontend/src/parser/parser.rs b/compiler/noirc_frontend/src/parser/parser.rs index cee824a51c9..6b8589cc6e5 100644 --- a/compiler/noirc_frontend/src/parser/parser.rs +++ b/compiler/noirc_frontend/src/parser/parser.rs @@ -26,8 +26,8 @@ use super::{ foldl_with_span, labels::ParsingRuleLabel, parameter_name_recovery, parameter_recovery, parenthesized, then_commit, then_commit_ignore, top_level_statement_recovery, ExprParser, - ForRange, NoirParser, ParsedModule, ParsedSubModule, ParserError, ParserErrorReason, - Precedence, TopLevelStatement, + NoirParser, ParsedModule, ParsedSubModule, ParserError, ParserErrorReason, Precedence, + TopLevelStatement, }; use super::{spanned, Item, ItemKind}; use crate::ast::{ @@ -38,11 +38,11 @@ use crate::parser::{force, ignore_then_commit, statement_recovery}; use crate::token::{Attribute, Attributes, Keyword, SecondaryAttribute, Token, TokenKind}; use crate::{ BinaryOp, BinaryOpKind, BlockExpression, ConstrainKind, ConstrainStatement, Distinctness, - FunctionDefinition, FunctionReturnType, FunctionVisibility, Ident, IfExpression, - InfixExpression, LValue, Lambda, Literal, NoirFunction, NoirStruct, NoirTrait, NoirTraitImpl, - NoirTypeAlias, Path, PathKind, Pattern, Recoverable, Statement, TraitBound, TraitImplItem, - TraitItem, TypeImpl, UnaryOp, UnresolvedTraitConstraint, UnresolvedTypeExpression, UseTree, - UseTreeKind, Visibility, + ForLoopStatement, ForRange, FunctionDefinition, FunctionReturnType, FunctionVisibility, Ident, + IfExpression, InfixExpression, LValue, Lambda, Literal, NoirFunction, NoirStruct, NoirTrait, + NoirTraitImpl, NoirTypeAlias, Param, Path, PathKind, Pattern, Recoverable, Statement, + TraitBound, TraitImplItem, TraitItem, TypeImpl, UnaryOp, UnresolvedTraitConstraint, + UnresolvedTypeExpression, UseTree, UseTreeKind, Visibility, }; use chumsky::prelude::*; @@ -177,12 +177,11 @@ fn function_definition(allow_self: bool) -> impl NoirParser { let ((((attributes, modifiers), name), generics), parameters) = args; // Validate collected attributes, filtering them into function and secondary variants - let attrs = validate_attributes(attributes, span, emit); - validate_where_clause(&generics, &where_clause, span, emit); + let attributes = validate_attributes(attributes, span, emit); FunctionDefinition { span: body_span, name, - attributes: attrs, + attributes, is_unconstrained: modifiers.0, is_open: modifiers.2, is_internal: modifiers.3, @@ -343,9 +342,7 @@ fn lambda_parameters() -> impl NoirParser> { .labelled(ParsingRuleLabel::Parameter) } -fn function_parameters<'a>( - allow_self: bool, -) -> impl NoirParser> + 'a { +fn function_parameters<'a>(allow_self: bool) -> impl NoirParser> + 'a { let typ = parse_type().recover_via(parameter_recovery()); let full_parameter = pattern() @@ -353,7 +350,12 @@ fn function_parameters<'a>( .then_ignore(just(Token::Colon)) .then(optional_visibility()) .then(typ) - .map(|((name, visibility), typ)| (name, typ, visibility)); + .map_with_span(|((pattern, visibility), typ), span| Param { + visibility, + pattern, + typ, + span, + }); let self_parameter = if allow_self { self_parameter().boxed() } else { nothing().boxed() }; @@ -370,7 +372,7 @@ fn nothing() -> impl NoirParser { one_of([]).map(|_| unreachable!()) } -fn self_parameter() -> impl NoirParser<(Pattern, UnresolvedType, Visibility)> { +fn self_parameter() -> impl NoirParser { let mut_ref_pattern = just(Token::Ampersand).then_ignore(keyword(Keyword::Mut)); let mut_pattern = keyword(Keyword::Mut); @@ -399,7 +401,7 @@ fn self_parameter() -> impl NoirParser<(Pattern, UnresolvedType, Visibility)> { _ => (), } - (pattern, self_type, Visibility::Private) + Param { pattern, typ: self_type, visibility: Visibility::Private, span } }) } @@ -412,7 +414,6 @@ fn trait_definition() -> impl NoirParser { .then(trait_body()) .then_ignore(just(Token::RightBrace)) .validate(|(((name, generics), where_clause), items), span, emit| { - validate_where_clause(&generics, &where_clause, span, emit); emit(ParserError::with_reason(ParserErrorReason::ExperimentalFeature("Traits"), span)); TopLevelStatement::Trait(NoirTrait { name, generics, where_clause, span, items }) }) @@ -451,12 +452,9 @@ fn trait_function_declaration() -> impl NoirParser { .then(function_return_type().map(|(_, typ)| typ)) .then(where_clause()) .then(trait_function_body_or_semicolon) - .validate( - |(((((name, generics), parameters), return_type), where_clause), body), span, emit| { - validate_where_clause(&generics, &where_clause, span, emit); - TraitItem::Function { name, generics, parameters, return_type, where_clause, body } - }, - ) + .map(|(((((name, generics), parameters), return_type), where_clause), body)| { + TraitItem::Function { name, generics, parameters, return_type, where_clause, body } + }) } fn validate_attributes( @@ -514,17 +512,6 @@ fn validate_struct_attributes( struct_attributes } -fn validate_where_clause( - generics: &Vec, - where_clause: &Vec, - span: Span, - emit: &mut dyn FnMut(ParserError), -) { - if !where_clause.is_empty() && generics.is_empty() { - emit(ParserError::with_reason(ParserErrorReason::WhereClauseOnNonGenericFunction, span)); - } -} - /// Function declaration parameters differ from other parameters in that parameter /// patterns are not allowed in declarations. All parameters must be identifiers. fn function_declaration_parameters() -> impl NoirParser> { @@ -533,8 +520,8 @@ fn function_declaration_parameters() -> impl NoirParser (ident, param.1), + match param.pattern { + Pattern::Identifier(ident) => (ident, param.typ), other => { emit(ParserError::with_reason( ParserErrorReason::PatternInTraitFunctionParameter, @@ -542,7 +529,7 @@ fn function_declaration_parameters() -> impl NoirParser(cases: &[Case], parser: P) + where + P: NoirParser + Clone, + T: std::fmt::Display, + { + let show_errors = |v| vecmap(&v, ToString::to_string).join("\n"); + + let results = vecmap(cases, |&case| { + let (opt, errors) = parse_recover(parser.clone(), case.source); + let actual = opt.map(|ast| ast.to_string()); + let actual = if let Some(s) = &actual { s.to_string() } else { "(none)".to_string() }; + + let result = ((errors.len(), actual.clone()), (case.errors, case.expect.to_string())); + if result.0 != result.1 { + let num_errors = errors.len(); + let shown_errors = show_errors(errors); + eprintln!( + concat!( + "\nExpected {expected_errors} error(s) and got {num_errors}:", + "\n\n{shown_errors}", + "\n\nFrom input: {src}", + "\nExpected AST: {expected_result}", + "\nActual AST: {actual}\n", + ), + expected_errors = case.errors, + num_errors = num_errors, + shown_errors = shown_errors, + src = case.source, + expected_result = case.expect, + actual = actual, + ); + } + result + }); + + assert_eq!(vecmap(&results, |t| t.0.clone()), vecmap(&results, |t| t.1.clone()),); + } + #[test] fn regression_skip_comment() { parse_all( @@ -2131,7 +2165,6 @@ mod test { "fn func_name(f: Field, y : pub Field, z : pub [u8;5],) where T: {}", "fn func_name(f: Field, y : pub Field, z : pub [u8;5],) where SomeTrait {}", "fn func_name(f: Field, y : pub Field, z : pub [u8;5],) SomeTrait {}", - "fn func_name(f: Field, y : pub Field, z : pub [u8;5],) where T: SomeTrait {}", // A leading plus is not allowed. "fn func_name(f: Field, y : T) where T: + SomeTrait {}", "fn func_name(f: Field, y : T) where T: TraitX + {}", @@ -2162,11 +2195,7 @@ mod test { parse_all_failing( trait_definition(), - vec![ - "trait MissingBody", - "trait WrongDelimiter { fn foo() -> u8, fn bar() -> u8 }", - "trait WhereClauseWithoutGenerics where A: SomeTrait { }", - ], + vec!["trait MissingBody", "trait WrongDelimiter { fn foo() -> u8, fn bar() -> u8 }"], ); } @@ -2407,116 +2436,117 @@ mod test { #[test] fn statement_recovery() { let cases = vec![ - ("let a = 4 + 3", 0, "let a: unspecified = (4 + 3)"), - ("let a: = 4 + 3", 1, "let a: error = (4 + 3)"), - ("let = 4 + 3", 1, "let $error: unspecified = (4 + 3)"), - ("let = ", 2, "let $error: unspecified = Error"), - ("let", 3, "let $error: unspecified = Error"), - ("foo = one two three", 1, "foo = plain::one"), - ("constrain", 2, "constrain Error"), - ("assert", 1, "constrain Error"), - ("constrain x ==", 2, "constrain (plain::x == Error)"), - ("assert(x ==)", 1, "constrain (plain::x == Error)"), - ("assert(x == x, x)", 1, "constrain (plain::x == plain::x)"), - ("assert_eq(x,)", 1, "constrain (Error == Error)"), - ("assert_eq(x, x, x, x)", 1, "constrain (Error == Error)"), - ("assert_eq(x, x, x)", 1, "constrain (plain::x == plain::x)"), + Case { source: "let a = 4 + 3", expect: "let a: unspecified = (4 + 3)", errors: 0 }, + Case { source: "let a: = 4 + 3", expect: "let a: error = (4 + 3)", errors: 1 }, + Case { source: "let = 4 + 3", expect: "let $error: unspecified = (4 + 3)", errors: 1 }, + Case { source: "let = ", expect: "let $error: unspecified = Error", errors: 2 }, + Case { source: "let", expect: "let $error: unspecified = Error", errors: 3 }, + Case { source: "foo = one two three", expect: "foo = plain::one", errors: 1 }, + Case { source: "constrain", expect: "constrain Error", errors: 2 }, + Case { source: "assert", expect: "constrain Error", errors: 1 }, + Case { source: "constrain x ==", expect: "constrain (plain::x == Error)", errors: 2 }, + Case { source: "assert(x ==)", expect: "constrain (plain::x == Error)", errors: 1 }, + Case { + source: "assert(x == x, x)", + expect: "constrain (plain::x == plain::x)", + errors: 1, + }, + Case { source: "assert_eq(x,)", expect: "constrain (Error == Error)", errors: 1 }, + Case { + source: "assert_eq(x, x, x, x)", + expect: "constrain (Error == Error)", + errors: 1, + }, + Case { + source: "assert_eq(x, x, x)", + expect: "constrain (plain::x == plain::x)", + errors: 1, + }, ]; - let show_errors = |v| vecmap(v, ToString::to_string).join("\n"); - - for (src, expected_errors, expected_result) in cases { - let (opt, errors) = parse_recover(fresh_statement(), src); - let actual = opt.map(|ast| ast.to_string()); - let actual = if let Some(s) = &actual { s } else { "(none)" }; - - assert_eq!((errors.len(), actual), (expected_errors, expected_result), - "\nExpected {} error(s) and got {}:\n\n{}\n\nFrom input: {}\nExpected AST: {}\nActual AST: {}\n", - expected_errors, errors.len(), show_errors(&errors), src, expected_result, actual - ); - } + check_cases_with_errors(&cases[..], fresh_statement()); } #[test] fn return_validation() { let cases = vec![ - ("{ return 42; }", 1, "{\n Error\n}"), - ("{ return 1; return 2; }", 2, "{\n Error\n Error\n}"), - ( - "{ return 123; let foo = 4 + 3; }", - 1, - "{\n Error\n let foo: unspecified = (4 + 3)\n}", - ), - ("{ return 1 + 2 }", 2, "{\n Error\n}"), - ("{ return; }", 1, "{\n Error\n}"), + Case { + source: "{ return 42; }", + expect: concat!("{\n", " Error\n", "}",), + errors: 1, + }, + Case { + source: "{ return 1; return 2; }", + expect: concat!("{\n", " Error\n", " Error\n", "}"), + errors: 2, + }, + Case { + source: "{ return 123; let foo = 4 + 3; }", + expect: concat!("{\n", " Error\n", " let foo: unspecified = (4 + 3)\n", "}"), + errors: 1, + }, + Case { + source: "{ return 1 + 2 }", + expect: concat!("{\n", " Error\n", "}",), + errors: 2, + }, + Case { source: "{ return; }", expect: concat!("{\n", " Error\n", "}",), errors: 1 }, ]; - let show_errors = |v| vecmap(&v, ToString::to_string).join("\n"); - - let results = vecmap(&cases, |&(src, expected_errors, expected_result)| { - let (opt, errors) = parse_recover(block(fresh_statement()), src); - let actual = opt.map(|ast| ast.to_string()); - let actual = if let Some(s) = &actual { s.to_string() } else { "(none)".to_string() }; - - let result = - ((errors.len(), actual.clone()), (expected_errors, expected_result.to_string())); - if result.0 != result.1 { - let num_errors = errors.len(); - let shown_errors = show_errors(errors); - eprintln!( - "\nExpected {expected_errors} error(s) and got {num_errors}:\n\n{shown_errors}\n\nFrom input: {src}\nExpected AST: {expected_result}\nActual AST: {actual}\n"); - } - result - }); - - assert_eq!(vecmap(&results, |t| t.0.clone()), vecmap(&results, |t| t.1.clone()),); + check_cases_with_errors(&cases[..], block(fresh_statement())); } #[test] fn expr_no_constructors() { let cases = vec![ - ( - "{ if structure { a: 1 } {} }", - 1, - "{\n if plain::structure {\n Error\n }\n {\n }\n}", - ), - ( - "{ if ( structure { a: 1 } ) {} }", - 0, - "{\n if ((plain::structure { a: 1 })) {\n }\n}", - ), - ("{ if ( structure {} ) {} }", 0, "{\n if ((plain::structure { })) {\n }\n}"), - ( - "{ if (a { x: 1 }, b { y: 2 }) {} }", - 0, - "{\n if ((plain::a { x: 1 }), (plain::b { y: 2 })) {\n }\n}", - ), - ( - "{ if ({ let foo = bar { baz: 42 }; foo == bar { baz: 42 }}) {} }", - 0, - "{\n if ({\n let foo: unspecified = (plain::bar { baz: 42 })\ - \n (plain::foo == (plain::bar { baz: 42 }))\n }) {\n }\n}", - ), + Case { + source: "{ if structure { a: 1 } {} }", + expect: concat!( + "{\n", + " if plain::structure {\n", + " Error\n", + " }\n", + " {\n", + " }\n", + "}", + ), + errors: 1, + }, + Case { + source: "{ if ( structure { a: 1 } ) {} }", + expect: concat!("{\n", " if ((plain::structure { a: 1 })) {\n", " }\n", "}",), + errors: 0, + }, + Case { + source: "{ if ( structure {} ) {} }", + expect: concat!("{\n", " if ((plain::structure { })) {\n", " }\n", "}"), + errors: 0, + }, + Case { + source: "{ if (a { x: 1 }, b { y: 2 }) {} }", + expect: concat!( + "{\n", + " if ((plain::a { x: 1 }), (plain::b { y: 2 })) {\n", + " }\n", + "}", + ), + errors: 0, + }, + Case { + source: "{ if ({ let foo = bar { baz: 42 }; foo == bar { baz: 42 }}) {} }", + expect: concat!( + "{\n", + " if ({\n", + " let foo: unspecified = (plain::bar { baz: 42 })\n", + " (plain::foo == (plain::bar { baz: 42 }))\n", + " }) {\n", + " }\n", + "}", + ), + errors: 0, + }, ]; - let show_errors = |v| vecmap(&v, ToString::to_string).join("\n"); - - let results = vecmap(&cases, |&(src, expected_errors, expected_result)| { - let (opt, errors) = parse_recover(block(fresh_statement()), src); - let actual = opt.map(|ast| ast.to_string()); - let actual = if let Some(s) = &actual { s.to_string() } else { "(none)".to_string() }; - - let result = - ((errors.len(), actual.clone()), (expected_errors, expected_result.to_string())); - if result.0 != result.1 { - let num_errors = errors.len(); - let shown_errors = show_errors(errors); - eprintln!( - "\nExpected {expected_errors} error(s) and got {num_errors}:\n\n{shown_errors}\n\nFrom input: {src}\nExpected AST: {expected_result}\nActual AST: {actual}\n"); - } - result - }); - - assert_eq!(vecmap(&results, |t| t.0.clone()), vecmap(&results, |t| t.1.clone()),); + check_cases_with_errors(&cases[..], block(fresh_statement())); } } diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index 91fce8d8862..6a1cf80accd 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -461,7 +461,7 @@ mod test { for (err, _file_id) in errors { match &err { - CompilationError::ResolveError(ResolverError::PathResolutionError( + CompilationError::ResolverError(ResolverError::PathResolutionError( PathResolutionError::Unresolved(ident), )) => { assert_eq!(ident, "NotAType"); @@ -533,18 +533,18 @@ mod test { } } - fn main() { - } + fn main() {} "; let errors = get_program_errors(src); assert!(!has_parser_error(&errors)); assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); for (err, _file_id) in errors { match &err { - CompilationError::DefinitionError( - DefCollectorErrorKind::TraitImplNotAllowedFor { trait_path, span: _ }, - ) => { - assert_eq!(trait_path.as_string(), "Default"); + CompilationError::ResolverError(ResolverError::Expected { + expected, got, .. + }) => { + assert_eq!(expected, "type"); + assert_eq!(got, "function"); } _ => { panic!("No other errors are expected! Found = {:?}", err); @@ -658,18 +658,15 @@ 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 { - CompilationError::DefinitionError(DefCollectorErrorKind::Duplicate { - typ, - first_def, - second_def, - }) => { - assert_eq!(typ, &DuplicateType::TraitImplementation); - assert_eq!(first_def, "Default"); - assert_eq!(second_def, "Default"); - } + CompilationError::DefinitionError(DefCollectorErrorKind::OverlappingImpl { + .. + }) => (), + CompilationError::DefinitionError(DefCollectorErrorKind::OverlappingImplNote { + .. + }) => (), _ => { panic!("No other errors are expected! Found = {:?}", err); } @@ -699,18 +696,15 @@ 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 { - CompilationError::DefinitionError(DefCollectorErrorKind::Duplicate { - typ, - first_def, - second_def, - }) => { - assert_eq!(typ, &DuplicateType::TraitImplementation); - assert_eq!(first_def, "Default"); - assert_eq!(second_def, "Default"); - } + CompilationError::DefinitionError(DefCollectorErrorKind::OverlappingImpl { + .. + }) => (), + CompilationError::DefinitionError(DefCollectorErrorKind::OverlappingImplNote { + .. + }) => (), _ => { panic!("No other errors are expected! Found = {:?}", err); } @@ -810,7 +804,7 @@ mod test { assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); // It should be regarding the unused variable match &errors[0].0 { - CompilationError::ResolveError(ResolverError::UnusedVariable { ident }) => { + CompilationError::ResolverError(ResolverError::UnusedVariable { ident }) => { assert_eq!(&ident.0.contents, "y"); } _ => unreachable!("we should only have an unused var error"), @@ -829,7 +823,7 @@ mod test { assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); // It should be regarding the unresolved var `z` (Maybe change to undeclared and special case) match &errors[0].0 { - CompilationError::ResolveError(ResolverError::VariableNotDeclared { + CompilationError::ResolverError(ResolverError::VariableNotDeclared { name, span: _, }) => assert_eq!(name, "z"), @@ -848,7 +842,7 @@ mod test { assert!(errors.len() == 1, "Expected 1 error, got: {:?}", errors); for (compilation_error, _file_id) in errors { match compilation_error { - CompilationError::ResolveError(err) => { + CompilationError::ResolverError(err) => { match err { ResolverError::PathResolutionError(PathResolutionError::Unresolved( name, @@ -892,7 +886,7 @@ mod test { // `foo::bar` does not exist for (compilation_error, _file_id) in errors { match compilation_error { - CompilationError::ResolveError(err) => { + CompilationError::ResolverError(err) => { match err { ResolverError::UnusedVariable { ident } => { assert_eq!(&ident.0.contents, "z"); @@ -1069,12 +1063,13 @@ mod test { for (err, _file_id) in errors { match &err { - CompilationError::ResolveError(ResolverError::VariableNotDeclared { - name, .. + CompilationError::ResolverError(ResolverError::VariableNotDeclared { + name, + .. }) => { assert_eq!(name, "i"); } - CompilationError::ResolveError(ResolverError::NumericConstantInFormatString { + CompilationError::ResolverError(ResolverError::NumericConstantInFormatString { name, .. }) => { diff --git a/compiler/readme.md b/compiler/readme.md index 7f7c3b86988..d95dce88c7c 100644 --- a/compiler/readme.md +++ b/compiler/readme.md @@ -1,32 +1,11 @@ # Structure -Below we briefly describe the purpose of each crate in this repository. - -## acir - Abstract Circuit Intermediate Representation - -This is the intermediate representation that Noir compiles down to. It is agnostic to any particular NP-Complete language. - -## acvm - Abstract Circuit Virtual Machine - -This is the virtual machine that runs ACIR. Given a proving system to power it, one can create and verify proofs, create smart contracts that verify proofs. +Below we briefly describe the purpose of each crate related to the compiler in this repository. ## fm - File Manager This is the abstraction that the compiler uses to manage source files. -## lsp - -This is the platform agnostic implementation of Noir's Language Server. It implements the various features supported, but doesn't bind to any particular transport. Binding to a transport must be done when consuming the crate. - -## nargo - -This is the default package manager used by Noir. One may draw similarities to Rusts' Cargo. - -## noir_field - -Since the DSL allows a user to create constants which can be as large as the field size, we must have a datatype that is able to store them. This is the purpose of the field crate. -One could alternatively use a BigInt library and store the modulus in a Context struct that gets passed to every compiler pass. - ## noirc_abi When consuming input from the user, a common ABI must be provided such that input provided in JSON/TOML can be converted to noir data types. This crate defines such an ABI. @@ -42,7 +21,3 @@ This crate can be seen as the middle end. It is in charge of generating the ACIR ## noirc_frontend This crate comprises of the first few compiler passes that together we denote as the compiler frontend (in order): lexing, parsing, name resolution, type checking, and monomorphization. If any of these passes error, the resulting monomorphized AST will not be passed to the middle-end (noirc_evaluator) - -## wasm - -This crate is used to compile the Noir compiler into wasm. This is useful in the context where one wants to compile noir programs in the web browser. \ No newline at end of file diff --git a/compiler/source-resolver/package.json b/compiler/source-resolver/package.json index 0726b544610..fb214a822eb 100644 --- a/compiler/source-resolver/package.json +++ b/compiler/source-resolver/package.json @@ -1,6 +1,6 @@ { "name": "@noir-lang/source-resolver", - "version": "0.18.0", + "version": "0.19.2", "license": "MIT", "main": "./lib-node/index_node.js", "types": "./types/index_node.d.ts", diff --git a/compiler/wasm/Cargo.toml b/compiler/wasm/Cargo.toml index b527e2de203..9ece26c6df4 100644 --- a/compiler/wasm/Cargo.toml +++ b/compiler/wasm/Cargo.toml @@ -22,16 +22,15 @@ wasm-bindgen.workspace = true serde.workspace = true js-sys.workspace = true cfg-if.workspace = true - -console_error_panic_hook = "0.1.7" -gloo-utils = { version = "0.1", features = ["serde"] } +console_error_panic_hook.workspace = true +gloo-utils.workspace = true log = "0.4.17" wasm-logger = "0.2.0" # This is an unused dependency, we are adding it # so that we can enable the js feature in getrandom. -getrandom = { version = "*", features = ["js"] } +getrandom = { workspace = true, features = ["js"] } [build-dependencies] -build-data = "0.1.3" +build-data.workspace = true diff --git a/compiler/wasm/fixtures/deps/lib-a/Nargo.toml b/compiler/wasm/fixtures/deps/lib-a/Nargo.toml index 3a02ccc1086..fa40b736619 100644 --- a/compiler/wasm/fixtures/deps/lib-a/Nargo.toml +++ b/compiler/wasm/fixtures/deps/lib-a/Nargo.toml @@ -2,7 +2,6 @@ name="lib_a" type="lib" authors = [""] -compiler_version = "0.1" [dependencies] lib_b = { path = "../lib-b" } diff --git a/compiler/wasm/fixtures/deps/lib-a/src/lib.nr b/compiler/wasm/fixtures/deps/lib-a/src/lib.nr index abb4302ba38..3f8fa051daf 100644 --- a/compiler/wasm/fixtures/deps/lib-a/src/lib.nr +++ b/compiler/wasm/fixtures/deps/lib-a/src/lib.nr @@ -1,4 +1,3 @@ - use dep::lib_b::assert_non_zero; pub fn divide(a: u64, b: u64) -> u64 { diff --git a/compiler/wasm/fixtures/deps/lib-b/Nargo.toml b/compiler/wasm/fixtures/deps/lib-b/Nargo.toml index 99db61e4bfa..904b6e14b90 100644 --- a/compiler/wasm/fixtures/deps/lib-b/Nargo.toml +++ b/compiler/wasm/fixtures/deps/lib-b/Nargo.toml @@ -2,6 +2,5 @@ name="lib_b" type="lib" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/compiler/wasm/fixtures/deps/lib-b/src/lib.nr b/compiler/wasm/fixtures/deps/lib-b/src/lib.nr index ad8b26020e3..a6db876ca56 100644 --- a/compiler/wasm/fixtures/deps/lib-b/src/lib.nr +++ b/compiler/wasm/fixtures/deps/lib-b/src/lib.nr @@ -1,4 +1,3 @@ - pub fn assert_non_zero(x: u64) { - assert(x != 0); + assert(x != 0); } diff --git a/compiler/wasm/fixtures/deps/noir-script/Nargo.toml b/compiler/wasm/fixtures/deps/noir-script/Nargo.toml index 0df22c2be7e..7c8182a02ae 100644 --- a/compiler/wasm/fixtures/deps/noir-script/Nargo.toml +++ b/compiler/wasm/fixtures/deps/noir-script/Nargo.toml @@ -2,7 +2,6 @@ name="noir_wasm_testing" type="bin" authors = [""] -compiler_version = "0.1" [dependencies] lib_a = { path="../lib-a" } diff --git a/compiler/wasm/fixtures/deps/noir-script/src/main.nr b/compiler/wasm/fixtures/deps/noir-script/src/main.nr index d46597fca2e..056bcc180b4 100644 --- a/compiler/wasm/fixtures/deps/noir-script/src/main.nr +++ b/compiler/wasm/fixtures/deps/noir-script/src/main.nr @@ -1,4 +1,4 @@ use dep::lib_a::divide; -fn main(x : u64, y : pub u64) { - divide(x, y); +fn main(x: u64, y: pub u64) { + divide(x, y); } diff --git a/compiler/wasm/fixtures/simple/noir-script/Nargo.toml b/compiler/wasm/fixtures/simple/noir-script/Nargo.toml index a8d4eb100f2..75499a08245 100644 --- a/compiler/wasm/fixtures/simple/noir-script/Nargo.toml +++ b/compiler/wasm/fixtures/simple/noir-script/Nargo.toml @@ -2,6 +2,5 @@ name="noir_wasm_testing" type="bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/compiler/wasm/fixtures/simple/noir-script/src/main.nr b/compiler/wasm/fixtures/simple/noir-script/src/main.nr index 36fcc1916f5..1ac4eac96b4 100644 --- a/compiler/wasm/fixtures/simple/noir-script/src/main.nr +++ b/compiler/wasm/fixtures/simple/noir-script/src/main.nr @@ -1,3 +1,3 @@ -fn main(x : u64, y : pub u64) { - assert(x < y); +fn main(x: u64, y: pub u64) { + assert(x < y); } diff --git a/compiler/wasm/package.json b/compiler/wasm/package.json index 3ed8d03cf5d..75b876e1db9 100644 --- a/compiler/wasm/package.json +++ b/compiler/wasm/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.18.0", + "version": "0.19.2", "license": "(MIT OR Apache-2.0)", "main": "./nodejs/noir_wasm.js", "types": "./web/noir_wasm.d.ts", diff --git a/compiler/wasm/src/circuit.rs b/compiler/wasm/src/circuit.rs index 97f9ef9cf18..fdd9a7d9a20 100644 --- a/compiler/wasm/src/circuit.rs +++ b/compiler/wasm/src/circuit.rs @@ -6,7 +6,7 @@ use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn acir_read_bytes(bytes: Vec) -> JsValue { console_error_panic_hook::set_once(); - let circuit = Circuit::read(&*bytes).unwrap(); + let circuit = Circuit::deserialize_circuit(&bytes).unwrap(); ::from_serde(&circuit).unwrap() } @@ -14,7 +14,5 @@ pub fn acir_read_bytes(bytes: Vec) -> JsValue { pub fn acir_write_bytes(acir: JsValue) -> Vec { console_error_panic_hook::set_once(); let circuit: Circuit = JsValueSerdeExt::into_serde(&acir).unwrap(); - let mut bytes = Vec::new(); - circuit.write(&mut bytes).unwrap(); - bytes + Circuit::serialize_circuit(&circuit) } diff --git a/compiler/wasm/src/compile.rs b/compiler/wasm/src/compile.rs index ac6219ee625..e7fd3dd5212 100644 --- a/compiler/wasm/src/compile.rs +++ b/compiler/wasm/src/compile.rs @@ -1,8 +1,9 @@ use fm::FileManager; use gloo_utils::format::JsValueSerdeExt; -use js_sys::Object; +use js_sys::{JsString, Object}; use nargo::artifacts::{ contract::{PreprocessedContract, PreprocessedContractFunction}, + debug::DebugArtifact, program::PreprocessedProgram, }; use noirc_driver::{ @@ -27,6 +28,38 @@ export type DependencyGraph = { root_dependencies: readonly string[]; library_dependencies: Readonly>; } + +export type CompiledContract = { + noir_version: string; + name: string; + backend: string; + functions: Array; + events: Array; +}; + +export type CompiledProgram = { + noir_version: string; + backend: string; + abi: any; + bytecode: string; +} + +export type DebugArtifact = { + debug_symbols: Array; + file_map: Record; + warnings: Array; +}; + +export type CompileResult = ( + | { + contract: CompiledContract; + debug: DebugArtifact; + } + | { + program: CompiledProgram; + debug: DebugArtifact; + } +); "#; #[wasm_bindgen] @@ -34,6 +67,57 @@ extern "C" { #[wasm_bindgen(extends = Object, js_name = "DependencyGraph", typescript_type = "DependencyGraph")] #[derive(Clone, Debug, PartialEq, Eq)] pub type JsDependencyGraph; + + #[wasm_bindgen(extends = Object, js_name = "CompileResult", typescript_type = "CompileResult")] + #[derive(Clone, Debug, PartialEq, Eq)] + pub type JsCompileResult; + + #[wasm_bindgen(constructor, js_class = "Object")] + fn constructor() -> JsCompileResult; +} + +impl JsCompileResult { + const CONTRACT_PROP: &'static str = "contract"; + const PROGRAM_PROP: &'static str = "program"; + const DEBUG_PROP: &'static str = "debug"; + + pub fn new(resp: CompileResult) -> JsCompileResult { + let obj = JsCompileResult::constructor(); + match resp { + CompileResult::Contract { contract, debug } => { + js_sys::Reflect::set( + &obj, + &JsString::from(JsCompileResult::CONTRACT_PROP), + &::from_serde(&contract).unwrap(), + ) + .unwrap(); + + js_sys::Reflect::set( + &obj, + &JsString::from(JsCompileResult::DEBUG_PROP), + &::from_serde(&debug).unwrap(), + ) + .unwrap(); + } + CompileResult::Program { program, debug } => { + js_sys::Reflect::set( + &obj, + &JsString::from(JsCompileResult::PROGRAM_PROP), + &::from_serde(&program).unwrap(), + ) + .unwrap(); + + js_sys::Reflect::set( + &obj, + &JsString::from(JsCompileResult::DEBUG_PROP), + &::from_serde(&debug).unwrap(), + ) + .unwrap(); + } + }; + + obj + } } #[derive(Deserialize)] @@ -42,12 +126,17 @@ struct DependencyGraph { library_dependencies: HashMap>, } +pub enum CompileResult { + Contract { contract: PreprocessedContract, debug: DebugArtifact }, + Program { program: PreprocessedProgram, debug: DebugArtifact }, +} + #[wasm_bindgen] pub fn compile( entry_point: String, contracts: Option, dependency_graph: Option, -) -> Result { +) -> Result { console_error_panic_hook::set_once(); let dependency_graph: DependencyGraph = if let Some(dependency_graph) = dependency_graph { @@ -89,9 +178,8 @@ pub fn compile( nargo::ops::optimize_contract(compiled_contract, np_language, &is_opcode_supported) .expect("Contract optimization failed"); - let preprocessed_contract = preprocess_contract(optimized_contract); - - Ok(::from_serde(&preprocessed_contract).unwrap()) + let compile_output = preprocess_contract(optimized_contract); + Ok(JsCompileResult::new(compile_output)) } else { let compiled_program = compile_main(&mut context, crate_id, &compile_options, None, true) .map_err(|errs| { @@ -107,9 +195,8 @@ pub fn compile( nargo::ops::optimize_program(compiled_program, np_language, &is_opcode_supported) .expect("Program optimization failed"); - let preprocessed_program = preprocess_program(optimized_program); - - Ok(::from_serde(&preprocessed_program).unwrap()) + let compile_output = preprocess_program(optimized_program); + Ok(JsCompileResult::new(compile_output)) } } @@ -145,17 +232,30 @@ fn add_noir_lib(context: &mut Context, library_name: &CrateName) -> CrateId { prepare_dependency(context, &path_to_lib) } -fn preprocess_program(program: CompiledProgram) -> PreprocessedProgram { - PreprocessedProgram { +fn preprocess_program(program: CompiledProgram) -> CompileResult { + let debug_artifact = DebugArtifact { + debug_symbols: vec![program.debug], + file_map: program.file_map, + warnings: program.warnings, + }; + + let preprocessed_program = PreprocessedProgram { hash: program.hash, backend: String::from(BACKEND_IDENTIFIER), abi: program.abi, noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(), bytecode: program.circuit, - } + }; + + CompileResult::Program { program: preprocessed_program, debug: debug_artifact } } -fn preprocess_contract(contract: CompiledContract) -> PreprocessedContract { +fn preprocess_contract(contract: CompiledContract) -> CompileResult { + let debug_artifact = DebugArtifact { + debug_symbols: contract.functions.iter().map(|function| function.debug.clone()).collect(), + file_map: contract.file_map, + warnings: contract.warnings, + }; let preprocessed_functions = contract .functions .into_iter() @@ -168,13 +268,15 @@ fn preprocess_contract(contract: CompiledContract) -> PreprocessedContract { }) .collect(); - PreprocessedContract { + let preprocessed_contract = PreprocessedContract { noir_version: String::from(NOIR_ARTIFACT_VERSION_STRING), name: contract.name, backend: String::from(BACKEND_IDENTIFIER), functions: preprocessed_functions, events: contract.events, - } + }; + + CompileResult::Contract { contract: preprocessed_contract, debug: debug_artifact } } cfg_if::cfg_if! { diff --git a/compiler/wasm/test/browser/index.test.ts b/compiler/wasm/test/browser/index.test.ts index cad2ada0c61..8a3f82ffff9 100644 --- a/compiler/wasm/test/browser/index.test.ts +++ b/compiler/wasm/test/browser/index.test.ts @@ -47,10 +47,14 @@ describe('noir wasm', () => { const wasmCircuit = await compile('/main.nr'); const cliCircuit = await getPrecompiledSource(simpleScriptExpectedArtifact); + if (!('program' in wasmCircuit)) { + throw Error('Expected program to be present'); + } + // We don't expect the hashes to match due to how `noir_wasm` handles dependencies - expect(wasmCircuit.bytecode).to.eq(cliCircuit.bytecode); - expect(wasmCircuit.abi).to.deep.eq(cliCircuit.abi); - expect(wasmCircuit.backend).to.eq(cliCircuit.backend); + expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); + expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); + expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); }).timeout(20e3); // 20 seconds }); @@ -87,12 +91,16 @@ describe('noir wasm', () => { }, }); + if (!('program' in wasmCircuit)) { + throw Error('Expected program to be present'); + } + const cliCircuit = await getPrecompiledSource(depsScriptExpectedArtifact); // We don't expect the hashes to match due to how `noir_wasm` handles dependencies - expect(wasmCircuit.bytecode).to.eq(cliCircuit.bytecode); - expect(wasmCircuit.abi).to.deep.eq(cliCircuit.abi); - expect(wasmCircuit.backend).to.eq(cliCircuit.backend); + expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); + expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); + expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); }).timeout(20e3); // 20 seconds }); }); diff --git a/compiler/wasm/test/node/index.test.ts b/compiler/wasm/test/node/index.test.ts index 2b430abdca4..c0d5f88e407 100644 --- a/compiler/wasm/test/node/index.test.ts +++ b/compiler/wasm/test/node/index.test.ts @@ -24,10 +24,14 @@ describe('noir wasm compilation', () => { const wasmCircuit = await compile(join(__dirname, simpleScriptSourcePath)); const cliCircuit = await getPrecompiledSource(simpleScriptExpectedArtifact); + if (!('program' in wasmCircuit)) { + throw Error('Expected program to be present'); + } + // We don't expect the hashes to match due to how `noir_wasm` handles dependencies - expect(wasmCircuit.bytecode).to.eq(cliCircuit.bytecode); - expect(wasmCircuit.abi).to.deep.eq(cliCircuit.abi); - expect(wasmCircuit.backend).to.eq(cliCircuit.backend); + expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); + expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); + expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); }).timeout(10e3); }); @@ -61,10 +65,14 @@ describe('noir wasm compilation', () => { const cliCircuit = await getPrecompiledSource(depsScriptExpectedArtifact); + if (!('program' in wasmCircuit)) { + throw Error('Expected program to be present'); + } + // We don't expect the hashes to match due to how `noir_wasm` handles dependencies - expect(wasmCircuit.bytecode).to.eq(cliCircuit.bytecode); - expect(wasmCircuit.abi).to.deep.eq(cliCircuit.abi); - expect(wasmCircuit.backend).to.eq(cliCircuit.backend); + expect(wasmCircuit.program.bytecode).to.eq(cliCircuit.bytecode); + expect(wasmCircuit.program.abi).to.deep.eq(cliCircuit.abi); + expect(wasmCircuit.program.backend).to.eq(cliCircuit.backend); }).timeout(10e3); }); }); diff --git a/cspell.json b/cspell.json index 4df858ffcfa..90d3963566d 100644 --- a/cspell.json +++ b/cspell.json @@ -15,6 +15,7 @@ "bitand", "blackbox", "brillig", + "cachix", "callsite", "callsites", "canonicalize", @@ -23,6 +24,7 @@ "clippy", "codegen", "codegens", + "codespan", "coeff", "combinators", "comptime", @@ -95,6 +97,7 @@ "sdiv", "secp256k1", "secp256r1", + "serde", "signedness", "smol", "splitn", diff --git a/deny.toml b/deny.toml index fc60154c628..d9ffd4d37f0 100644 --- a/deny.toml +++ b/deny.toml @@ -52,8 +52,6 @@ allow = [ "Zlib", # https://github.com/briansmith/ring/issues/902 "LicenseRef-ring", - # https://github.com/briansmith/webpki/issues/148 - "LicenseRef-webpki", # https://github.com/rustls/webpki/blob/main/LICENSE ISC Style "LicenseRef-rustls-webpki", # bitmaps 2.1.0, generational-arena 0.2.9,im 15.1.0 @@ -79,11 +77,6 @@ name = "ring" expression = "LicenseRef-ring" license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }] -[[licenses.clarify]] -name = "webpki" -expression = "LicenseRef-webpki" -license-files = [{ path = "LICENSE", hash = 0x001c7e6c }] - [[licenses.clarify]] name = "rustls-webpki" expression = "LicenseRef-rustls-webpki" diff --git a/docs/.gitignore b/docs/.gitignore index 96ecf9cbc03..e76d8caf6bc 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -7,6 +7,7 @@ # Generated files .docusaurus .cache-loader +/docs/noir_js/reference/ # Misc .DS_Store @@ -20,4 +21,4 @@ npm-debug.log* yarn-debug.log* yarn-error.log* -package-lock.json +package-lock.json \ No newline at end of file diff --git a/docs/docs/examples/merkle-proof.mdx b/docs/docs/examples/merkle-proof.mdx index 6430780817c..832fb4bb55e 100644 --- a/docs/docs/examples/merkle-proof.mdx +++ b/docs/docs/examples/merkle-proof.mdx @@ -23,7 +23,7 @@ fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Fie 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` +random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` instead. ```rust diff --git a/docs/docs/getting_started/00_nargo_installation.md b/docs/docs/getting_started/00_nargo_installation.md index 26a665a0d51..725c5f4d373 100644 --- a/docs/docs/getting_started/00_nargo_installation.md +++ b/docs/docs/getting_started/00_nargo_installation.md @@ -23,8 +23,8 @@ 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) +- [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. @@ -98,21 +98,6 @@ 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 @@ -220,7 +205,7 @@ code . #### 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. +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: @@ -233,6 +218,14 @@ If you have hesitations with using direnv, you can launch a subshell with `nix d 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 diff --git a/docs/docs/getting_started/02_breakdown.md b/docs/docs/getting_started/02_breakdown.md index bc0e742fb4e..9a17f5d6360 100644 --- a/docs/docs/getting_started/02_breakdown.md +++ b/docs/docs/getting_started/02_breakdown.md @@ -66,7 +66,7 @@ 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. +- `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) diff --git a/docs/docs/index.md b/docs/docs/index.md index 9ebe1d54944..75e1abf2932 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -79,7 +79,8 @@ ACIR Supported OPCODES: - Blake2s - Schnorr signature verification - MerkleMembership -- Pedersen +- Pedersen Commitment +- Pedersen Hash - HashToField ## Libraries diff --git a/docs/docs/language_concepts/06_generics.md b/docs/docs/language_concepts/06_generics.md index b700bd5bc5b..9fb4177c2a8 100644 --- a/docs/docs/language_concepts/06_generics.md +++ b/docs/docs/language_concepts/06_generics.md @@ -110,4 +110,4 @@ fn main() { ``` 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). +[here](https://github.com/noir-lang/noir/blob/master/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). diff --git a/docs/docs/language_concepts/data_types/01_integers.md b/docs/docs/language_concepts/data_types/01_integers.md index d9c5e20e795..b1e7ad11bfd 100644 --- a/docs/docs/language_concepts/data_types/01_integers.md +++ b/docs/docs/language_concepts/data_types/01_integers.md @@ -1,33 +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, - ] +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 a range constrained field type. The Noir frontend supports arbitrarily-sized, both unsigned and signed 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]\\)$: +:::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 : Field, y : u32) { - let z = x as u32 + y; +fn main(x: u8, y: u8) { + let z = x + 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. +With: -> **Note:** The default backend supports both even (e.g. `u16`, `u48`) and odd (e.g. `u5`, `u3`) -> sized integer types. +```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/language_concepts/data_types/05_slices.mdx b/docs/docs/language_concepts/data_types/05_slices.mdx index 7fd07225a4e..1be0ec4a137 100644 --- a/docs/docs/language_concepts/data_types/05_slices.mdx +++ b/docs/docs/language_concepts/data_types/05_slices.mdx @@ -4,7 +4,7 @@ description: Explore the Slice data type in Noir. Understand its methods, see re keywords: [noir, slice type, methods, examples, subarrays] --- -import Experimental from '../../../src/components/Notes/_experimental.mdx'; +import Experimental from '@site/src/components/Notes/_experimental.mdx'; @@ -21,7 +21,7 @@ fn main() -> pub Field { } ``` -View the corresponding test file [here]([test-file]. +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 diff --git a/docs/docs/language_concepts/data_types/06_vectors.mdx b/docs/docs/language_concepts/data_types/06_vectors.mdx index 4d3406f20c0..4617e90d038 100644 --- a/docs/docs/language_concepts/data_types/06_vectors.mdx +++ b/docs/docs/language_concepts/data_types/06_vectors.mdx @@ -4,7 +4,7 @@ description: Delve into the Vector data type in Noir. Learn about its methods, p keywords: [noir, vector type, methods, examples, dynamic arrays] --- -import Experimental from '../../../src/components/Notes/_experimental.mdx'; +import Experimental from '@site/src/components/Notes/_experimental.mdx'; diff --git a/docs/docs/language_concepts/data_types/08_structs.md b/docs/docs/language_concepts/data_types/08_structs.md index 85649dfb389..35421734639 100644 --- a/docs/docs/language_concepts/data_types/08_structs.md +++ b/docs/docs/language_concepts/data_types/08_structs.md @@ -67,7 +67,3 @@ fn get_octopus() -> Animal { 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/docs/migration_notes.md b/docs/docs/migration_notes.md index 48a8abcf22e..e87eb1feaba 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -6,6 +6,14 @@ 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: diff --git a/docs/docs/modules_packages_crates/workspaces.md b/docs/docs/modules_packages_crates/workspaces.md index d9ac92667c9..a979ef9f0a5 100644 --- a/docs/docs/modules_packages_crates/workspaces.md +++ b/docs/docs/modules_packages_crates/workspaces.md @@ -36,4 +36,4 @@ default-member = "crates/a" 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. +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. \ No newline at end of file diff --git a/docs/docs/nargo/04_language_server.md b/docs/docs/nargo/04_language_server.md index 144cd249c4b..48c01465f6e 100644 --- a/docs/docs/nargo/04_language_server.md +++ b/docs/docs/nargo/04_language_server.md @@ -27,12 +27,12 @@ Currently, Noir provides a Language Client for Visual Studio Code via the [vscod 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](./../../static/img/codelens_compile_execute.png) -![Run test](../../static/img/codelens_run_test.png) +![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](./../../static/img/codelens_testing_panel.png) +![Testing panel](@site/static/img/codelens_testing_panel.png) ### Configuration diff --git a/docs/docs/noir_js/getting_started/01_tiny_noir_app.md b/docs/docs/noir_js/getting_started/01_tiny_noir_app.md index 1b0c8bfc353..c51ed61de52 100644 --- a/docs/docs/noir_js/getting_started/01_tiny_noir_app.md +++ b/docs/docs/noir_js/getting_started/01_tiny_noir_app.md @@ -6,6 +6,8 @@ keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowl 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 @@ -45,7 +47,7 @@ Go back to the previous folder and start a new project by running run `npm init` 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 +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: @@ -235,7 +237,7 @@ 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](./../../../static/img/noir_getting_started_1.png) +![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. @@ -249,6 +251,8 @@ 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. diff --git a/docs/docs/noir_js/noir_js.md b/docs/docs/noir_js/noir_js.md index 23ea550e156..f895b22eaf8 100644 --- a/docs/docs/noir_js/noir_js.md +++ b/docs/docs/noir_js/noir_js.md @@ -33,4 +33,4 @@ To install its JavaScript library, run this in your project: 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. +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/docs/standard_library/black_box_fns.md b/docs/docs/standard_library/black_box_fns.md index c758846b688..1dfabfe8f22 100644 --- a/docs/docs/standard_library/black_box_fns.md +++ b/docs/docs/standard_library/black_box_fns.md @@ -29,7 +29,8 @@ Here is a list of the current black box functions that are supported by UltraPlo - [SHA256](./cryptographic_primitives/hashes#sha256) - [Schnorr signature verification](./cryptographic_primitives/schnorr) - [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen](./cryptographic_primitives/hashes#pedersen) +- [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) diff --git a/docs/docs/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/docs/standard_library/cryptographic_primitives/00_hashes.mdx index bb2621b6499..76745196681 100644 --- a/docs/docs/standard_library/cryptographic_primitives/00_hashes.mdx +++ b/docs/docs/standard_library/cryptographic_primitives/00_hashes.mdx @@ -7,7 +7,7 @@ keywords: [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] --- -import BlackBoxInfo from '../../../src/components/Notes/_blackbox.mdx'; +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; ## sha256 @@ -47,12 +47,12 @@ fn main() { -## pedersen +## pedersen_hash Given an array of Fields, returns the Pedersen hash. ```rust -fn pedersen(_input : [Field]) -> [Field; 2] +fn pedersen_hash(_input : [Field]) -> Field ``` example: @@ -60,7 +60,28 @@ example: ```rust fn main() { let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::pedersen(x); + 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); } ``` @@ -130,7 +151,7 @@ example: fn main() { let x = [163, 117, 178, 149]; // some random bytes - let hash = std::hash::mimc_bn254(x); + let hash = std::hash::mimc::mimc_bn254(x); } ``` diff --git a/docs/docs/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/docs/standard_library/cryptographic_primitives/01_scalar.mdx index 0d7990859b5..c7eed820a80 100644 --- a/docs/docs/standard_library/cryptographic_primitives/01_scalar.mdx +++ b/docs/docs/standard_library/cryptographic_primitives/01_scalar.mdx @@ -4,7 +4,7 @@ description: See how you can perform scalar multiplications over a fixed base in keywords: [cryptographic primitives, Noir project, scalar multiplication] --- -import BlackBoxInfo from '../../../src/components/Notes/_blackbox.mdx'; +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; ## scalar_mul::fixed_base_embedded_curve diff --git a/docs/docs/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/docs/standard_library/cryptographic_primitives/02_schnorr.mdx index 73737eb54bb..c184ce28120 100644 --- a/docs/docs/standard_library/cryptographic_primitives/02_schnorr.mdx +++ b/docs/docs/standard_library/cryptographic_primitives/02_schnorr.mdx @@ -4,7 +4,7 @@ description: Learn how you can verify Schnorr signatures using Noir keywords: [cryptographic primitives, Noir project, schnorr, signatures] --- -import BlackBoxInfo from '../../../src/components/Notes/_blackbox.mdx'; +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; ## schnorr::verify_signature diff --git a/docs/docs/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/docs/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx index 25185b062f7..72bce984821 100644 --- a/docs/docs/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx +++ b/docs/docs/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx @@ -4,7 +4,7 @@ description: Learn about the cryptographic primitives regarding ECDSA over the s keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] --- -import BlackBoxInfo from '../../../src/components/Notes/_blackbox.mdx'; +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. diff --git a/docs/docs/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/docs/standard_library/cryptographic_primitives/05_eddsa.mdx index 39dfb604669..9a5beb55ee9 100644 --- a/docs/docs/standard_library/cryptographic_primitives/05_eddsa.mdx +++ b/docs/docs/standard_library/cryptographic_primitives/05_eddsa.mdx @@ -4,7 +4,7 @@ description: Learn about the cryptographic primitives regarding EdDSA keywords: [cryptographic primitives, Noir project, eddsa, signatures] --- -import BlackBoxInfo from '../../../src/components/Notes/_blackbox.mdx'; +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; ## eddsa::eddsa_poseidon_verify diff --git a/docs/docs/standard_library/merkle_trees.md b/docs/docs/standard_library/merkle_trees.md index 9761105f4f2..dc383a1426b 100644 --- a/docs/docs/standard_library/merkle_trees.md +++ b/docs/docs/standard_library/merkle_trees.md @@ -17,7 +17,7 @@ keywords: ## 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). +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 diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index ff07b5697ce..8f62df3d0e9 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -45,9 +45,6 @@ const config = { label: 'dev', path: 'dev', }, - '0.7.1': { - label: '0.7.1 / 0.8.0', - }, }, editUrl: ({ versionDocsDirPath, docPath }) => `https://github.com/noir-lang/noir/edit/master/docs/${versionDocsDirPath}/${docPath}`, @@ -62,7 +59,7 @@ const config = { themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ - ({ + { // Replace with your project's social card navbar: { logo: { @@ -87,8 +84,7 @@ const config = { metadata: [ { name: 'Noir', - content: - 'noir, programming, language, documentation, zk, zero-knowledge, l2, crypto, layer2, ethereum', + content: 'noir, programming, language, documentation, zk, zero-knowledge, l2, crypto, layer2, ethereum', }, ], footer: { @@ -149,7 +145,71 @@ const config = { 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/package.json b/docs/package.json index edf4bba0686..09f8d718b56 100644 --- a/docs/package.json +++ b/docs/package.json @@ -4,7 +4,8 @@ "private": true, "scripts": { "start": "docusaurus start", - "build": "docusaurus build" + "build": "docusaurus build", + "setStable": "node ./scripts/setStable.js" }, "dependencies": { "@docusaurus/core": "^2.4.0", @@ -14,12 +15,18 @@ "@mdx-js/react": "^1.6.22", "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" + "remark-math": "^3.0.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" diff --git a/docs/scripts/setStable.js b/docs/scripts/setStable.js new file mode 100644 index 00000000000..4bbe283f4be --- /dev/null +++ b/docs/scripts/setStable.js @@ -0,0 +1,42 @@ +/* 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/sidebars.js b/docs/sidebars.js index 8fddb677a58..3fd391cf09c 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -119,8 +119,22 @@ const sidebars = { label: 'Reference', items: [ { - type: 'autogenerated', - dirName: 'noir_js/reference', + 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'), }, ], }, diff --git a/docs/versioned_docs/version-0.10.5/examples/merkle-proof.mdx b/docs/versioned_docs/version-v0.10.5/examples/merkle-proof.mdx similarity index 100% rename from docs/versioned_docs/version-0.10.5/examples/merkle-proof.mdx rename to docs/versioned_docs/version-v0.10.5/examples/merkle-proof.mdx diff --git a/docs/versioned_docs/version-0.10.5/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/getting_started/00_nargo_installation.md rename to docs/versioned_docs/version-v0.10.5/getting_started/00_nargo_installation.md diff --git a/docs/versioned_docs/version-0.10.5/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.10.5/getting_started/01_hello_world.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/getting_started/01_hello_world.md rename to docs/versioned_docs/version-v0.10.5/getting_started/01_hello_world.md diff --git a/docs/versioned_docs/version-0.10.5/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.10.5/getting_started/02_breakdown.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/getting_started/02_breakdown.md rename to docs/versioned_docs/version-v0.10.5/getting_started/02_breakdown.md diff --git a/docs/versioned_docs/version-0.10.5/getting_started/03_language_server.md b/docs/versioned_docs/version-v0.10.5/getting_started/03_language_server.md similarity index 94% rename from docs/versioned_docs/version-0.10.5/getting_started/03_language_server.md rename to docs/versioned_docs/version-v0.10.5/getting_started/03_language_server.md index f2de55cfb7c..49bd1d24675 100644 --- a/docs/versioned_docs/version-0.10.5/getting_started/03_language_server.md +++ b/docs/versioned_docs/version-v0.10.5/getting_started/03_language_server.md @@ -25,8 +25,8 @@ Currently, Noir provides a Language Client for Visual Studio Code via the [vscod 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](./../../../static/img/codelens_compile_execute.png) -![Run test](../../../static/img/codelens_run_test.png) +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) ### Configuration diff --git a/docs/versioned_docs/version-0.10.5/index.md b/docs/versioned_docs/version-v0.10.5/index.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/index.md rename to docs/versioned_docs/version-v0.10.5/index.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.10.5/language_concepts/01_functions.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/01_functions.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/01_functions.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.10.5/language_concepts/02_control_flow.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/02_control_flow.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/02_control_flow.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/03_ops.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/03_ops.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.10.5/language_concepts/04_assert.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/04_assert.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/04_assert.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.10.5/language_concepts/05_unconstrained.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/05_unconstrained.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/05_unconstrained.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.10.5/language_concepts/06_generics.md similarity index 96% rename from docs/versioned_docs/version-0.10.5/language_concepts/06_generics.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/06_generics.md index b700bd5bc5b..9fb4177c2a8 100644 --- a/docs/versioned_docs/version-0.10.5/language_concepts/06_generics.md +++ b/docs/versioned_docs/version-v0.10.5/language_concepts/06_generics.md @@ -110,4 +110,4 @@ fn main() { ``` 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). +[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-0.10.5/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.10.5/language_concepts/07_mutability.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/07_mutability.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/07_mutability.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/08_lambdas.md b/docs/versioned_docs/version-v0.10.5/language_concepts/08_lambdas.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/08_lambdas.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/08_lambdas.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/09_comments.md b/docs/versioned_docs/version-v0.10.5/language_concepts/09_comments.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/09_comments.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/09_comments.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/10_distinct.md b/docs/versioned_docs/version-v0.10.5/language_concepts/10_distinct.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/10_distinct.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/10_distinct.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/11_shadowing.md b/docs/versioned_docs/version-v0.10.5/language_concepts/11_shadowing.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/11_shadowing.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/11_shadowing.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/data_types.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/data_types.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/data_types.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/data_types/00_fields.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/data_types/00_fields.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/data_types/01_integers.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/01_integers.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/data_types/01_integers.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/data_types/01_integers.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/02_booleans.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/data_types/02_booleans.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/data_types/02_booleans.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/03_strings.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/data_types/03_strings.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/data_types/03_strings.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/04_arrays.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/data_types/04_arrays.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/data_types/04_arrays.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/data_types/05_slices.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/05_slices.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/data_types/05_slices.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/data_types/05_slices.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/data_types/06_vectors.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/06_vectors.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/data_types/06_vectors.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/data_types/06_vectors.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/data_types/07_tuples.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/07_tuples.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/data_types/07_tuples.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/data_types/07_tuples.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/data_types/08_structs.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/08_structs.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/data_types/08_structs.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/data_types/08_structs.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/data_types/09_references.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/09_references.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/data_types/09_references.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/data_types/09_references.md diff --git a/docs/versioned_docs/version-0.10.5/language_concepts/data_types/10_function_types.md b/docs/versioned_docs/version-v0.10.5/language_concepts/data_types/10_function_types.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/language_concepts/data_types/10_function_types.md rename to docs/versioned_docs/version-v0.10.5/language_concepts/data_types/10_function_types.md diff --git a/docs/versioned_docs/version-0.10.5/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.10.5/modules_packages_crates/crates_and_packages.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/modules_packages_crates/crates_and_packages.md rename to docs/versioned_docs/version-v0.10.5/modules_packages_crates/crates_and_packages.md diff --git a/docs/versioned_docs/version-0.10.5/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.10.5/modules_packages_crates/dependencies.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/modules_packages_crates/dependencies.md rename to docs/versioned_docs/version-v0.10.5/modules_packages_crates/dependencies.md diff --git a/docs/versioned_docs/version-0.10.5/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.10.5/modules_packages_crates/modules.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/modules_packages_crates/modules.md rename to docs/versioned_docs/version-v0.10.5/modules_packages_crates/modules.md diff --git a/docs/versioned_docs/version-0.10.5/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.10.5/modules_packages_crates/workspaces.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/modules_packages_crates/workspaces.md rename to docs/versioned_docs/version-v0.10.5/modules_packages_crates/workspaces.md diff --git a/docs/versioned_docs/version-0.10.5/nargo/01_commands.md b/docs/versioned_docs/version-v0.10.5/nargo/01_commands.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/nargo/01_commands.md rename to docs/versioned_docs/version-v0.10.5/nargo/01_commands.md diff --git a/docs/versioned_docs/version-0.10.5/nargo/02_testing.md b/docs/versioned_docs/version-v0.10.5/nargo/02_testing.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/nargo/02_testing.md rename to docs/versioned_docs/version-v0.10.5/nargo/02_testing.md diff --git a/docs/versioned_docs/version-0.10.5/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.10.5/nargo/03_solidity_verifier.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/nargo/03_solidity_verifier.md rename to docs/versioned_docs/version-v0.10.5/nargo/03_solidity_verifier.md diff --git a/docs/versioned_docs/version-0.10.5/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.10.5/standard_library/black_box_fns.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/black_box_fns.md rename to docs/versioned_docs/version-v0.10.5/standard_library/black_box_fns.md diff --git a/docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives.md rename to docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives.md diff --git a/docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/00_hashes.mdx similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/00_hashes.mdx rename to docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/00_hashes.mdx diff --git a/docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/01_scalar.mdx similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/01_scalar.mdx rename to docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/01_scalar.mdx diff --git a/docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/02_schnorr.mdx similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/02_schnorr.mdx rename to docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/02_schnorr.mdx diff --git a/docs/versioned_docs/version-0.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 similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx rename to docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx diff --git a/docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/04_ec_primitives.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/04_ec_primitives.md rename to docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/04_ec_primitives.md diff --git a/docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/05_eddsa.mdx similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/05_eddsa.mdx rename to docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/05_eddsa.mdx diff --git a/docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/common/_blackbox.mdx b/docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/common/_blackbox.mdx similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/cryptographic_primitives/common/_blackbox.mdx rename to docs/versioned_docs/version-v0.10.5/standard_library/cryptographic_primitives/common/_blackbox.mdx diff --git a/docs/versioned_docs/version-0.10.5/standard_library/logging.md b/docs/versioned_docs/version-v0.10.5/standard_library/logging.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/logging.md rename to docs/versioned_docs/version-v0.10.5/standard_library/logging.md diff --git a/docs/versioned_docs/version-0.10.5/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.10.5/standard_library/merkle_trees.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/merkle_trees.md rename to docs/versioned_docs/version-v0.10.5/standard_library/merkle_trees.md diff --git a/docs/versioned_docs/version-0.10.5/standard_library/options.md b/docs/versioned_docs/version-v0.10.5/standard_library/options.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/options.md rename to docs/versioned_docs/version-v0.10.5/standard_library/options.md diff --git a/docs/versioned_docs/version-0.10.5/standard_library/recursion.md b/docs/versioned_docs/version-v0.10.5/standard_library/recursion.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/recursion.md rename to docs/versioned_docs/version-v0.10.5/standard_library/recursion.md diff --git a/docs/versioned_docs/version-0.10.5/standard_library/zeroed.md b/docs/versioned_docs/version-v0.10.5/standard_library/zeroed.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/standard_library/zeroed.md rename to docs/versioned_docs/version-v0.10.5/standard_library/zeroed.md diff --git a/docs/versioned_docs/version-0.10.5/typescript.md b/docs/versioned_docs/version-v0.10.5/typescript.md similarity index 100% rename from docs/versioned_docs/version-0.10.5/typescript.md rename to docs/versioned_docs/version-v0.10.5/typescript.md diff --git a/docs/versioned_docs/version-0.9.0/examples/merkle-proof.mdx b/docs/versioned_docs/version-v0.17.0/examples/merkle-proof.mdx similarity index 100% rename from docs/versioned_docs/version-0.9.0/examples/merkle-proof.mdx rename to docs/versioned_docs/version-v0.17.0/examples/merkle-proof.mdx 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 new file mode 100644 index 00000000000..4ff5fc46334 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.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 `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! + +### Option 4: WSL (for Windows) + +Windows is not directly supported at this time. To install Noir on a Windows machine, it is recommended to use 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.17.0/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md new file mode 100644 index 00000000000..8b4416beba1 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md new file mode 100644 index 00000000000..bc0e742fb4e --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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` (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. diff --git a/docs/versioned_docs/version-v0.17.0/index.md b/docs/versioned_docs/version-v0.17.0/index.md new file mode 100644 index 00000000000..9ebe1d54944 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/index.md @@ -0,0 +1,99 @@ +--- +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 +- 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.17.0/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.17.0/language_concepts/01_functions.md new file mode 100644 index 00000000000..47cdea0cf04 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.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 : 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/versioned_docs/version-v0.17.0/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.17.0/language_concepts/02_control_flow.md new file mode 100644 index 00000000000..a7f85360197 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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-0.7.1/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/language_concepts/03_ops.md rename to docs/versioned_docs/version-v0.17.0/language_concepts/03_ops.md diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.17.0/language_concepts/04_assert.md new file mode 100644 index 00000000000..7427ec6cc63 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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-0.9.0/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.17.0/language_concepts/05_unconstrained.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/language_concepts/05_unconstrained.md rename to docs/versioned_docs/version-v0.17.0/language_concepts/05_unconstrained.md diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.17.0/language_concepts/06_generics.md new file mode 100644 index 00000000000..9fb4177c2a8 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.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/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). 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 new file mode 100644 index 00000000000..4641521b1d9 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.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() -> 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.17.0/language_concepts/08_lambdas.md b/docs/versioned_docs/version-v0.17.0/language_concepts/08_lambdas.md new file mode 100644 index 00000000000..ae1e6aecab1 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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-0.9.0/language_concepts/08_comments.md b/docs/versioned_docs/version-v0.17.0/language_concepts/09_comments.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/language_concepts/08_comments.md rename to docs/versioned_docs/version-v0.17.0/language_concepts/09_comments.md diff --git a/docs/versioned_docs/version-0.9.0/language_concepts/09_distinct.md b/docs/versioned_docs/version-v0.17.0/language_concepts/10_distinct.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/language_concepts/09_distinct.md rename to docs/versioned_docs/version-v0.17.0/language_concepts/10_distinct.md diff --git a/docs/versioned_docs/version-0.9.0/language_concepts/10_shadowing.md b/docs/versioned_docs/version-v0.17.0/language_concepts/11_shadowing.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/language_concepts/10_shadowing.md rename to docs/versioned_docs/version-v0.17.0/language_concepts/11_shadowing.md diff --git a/docs/versioned_docs/version-v0.17.0/language_concepts/data_types.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types.md new file mode 100644 index 00000000000..d546cc463a8 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/00_fields.md new file mode 100644 index 00000000000..658a0441ffb --- /dev/null +++ b/docs/versioned_docs/version-v0.17.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/versioned_docs/version-v0.17.0/language_concepts/data_types/01_integers.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/01_integers.md new file mode 100644 index 00000000000..d9c5e20e795 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/01_integers.md @@ -0,0 +1,33 @@ +--- +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.17.0/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md new file mode 100644 index 00000000000..885db167d83 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md new file mode 100644 index 00000000000..c42f34ec3ad --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md new file mode 100644 index 00000000000..bdbd1798bef --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/language_concepts/data_types/05_slices.mdx b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/05_slices.mdx new file mode 100644 index 00000000000..f45f56daee1 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/language_concepts/data_types/06_vectors.mdx b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/06_vectors.mdx new file mode 100644 index 00000000000..4617e90d038 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/language_concepts/data_types/07_tuples.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/07_tuples.md new file mode 100644 index 00000000000..5f6cab974a8 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/language_concepts/data_types/08_structs.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/08_structs.md new file mode 100644 index 00000000000..85649dfb389 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/08_structs.md @@ -0,0 +1,73 @@ +--- +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. + +:::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.17.0/language_concepts/data_types/09_references.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/09_references.md new file mode 100644 index 00000000000..b0c35ce2cb9 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/language_concepts/data_types/10_function_types.md b/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/10_function_types.md new file mode 100644 index 00000000000..1ec92efd594 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/migration_notes.md b/docs/versioned_docs/version-v0.17.0/migration_notes.md new file mode 100644 index 00000000000..48a8abcf22e --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/migration_notes.md @@ -0,0 +1,83 @@ +--- +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.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: , 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.17.0/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.17.0/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..fb83a33d94e --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..75f95aaa305 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.17.0/modules_packages_crates/modules.md new file mode 100644 index 00000000000..147c9b284e8 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.17.0/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..d9ac92667c9 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.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/versioned_docs/version-v0.17.0/nargo/01_commands.md b/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md new file mode 100644 index 00000000000..65e2bdb44e3 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/nargo/02_testing.md b/docs/versioned_docs/version-v0.17.0/nargo/02_testing.md new file mode 100644 index 00000000000..da767274efd --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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-0.7.1/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.17.0/nargo/03_solidity_verifier.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/nargo/03_solidity_verifier.md rename to docs/versioned_docs/version-v0.17.0/nargo/03_solidity_verifier.md diff --git a/docs/versioned_docs/version-v0.17.0/nargo/04_language_server.md b/docs/versioned_docs/version-v0.17.0/nargo/04_language_server.md new file mode 100644 index 00000000000..48c01465f6e --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/noir_js/getting_started/01_tiny_noir_app.md b/docs/versioned_docs/version-v0.17.0/noir_js/getting_started/01_tiny_noir_app.md new file mode 100644 index 00000000000..6955f7a1e64 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/noir_js/getting_started/01_tiny_noir_app.md @@ -0,0 +1,256 @@ +--- +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. + +## 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! + +## 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.17.0/noir_js/noir_js.md b/docs/versioned_docs/version-v0.17.0/noir_js/noir_js.md new file mode 100644 index 00000000000..23ea550e156 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.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/docs/noir_js/reference/01_noirjs.md b/docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md similarity index 100% rename from docs/docs/noir_js/reference/01_noirjs.md rename to docs/versioned_docs/version-v0.17.0/noir_js/reference/01_noirjs.md diff --git a/docs/docs/noir_js/reference/02_bb_backend.md b/docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md similarity index 100% rename from docs/docs/noir_js/reference/02_bb_backend.md rename to docs/versioned_docs/version-v0.17.0/noir_js/reference/02_bb_backend.md diff --git a/docs/versioned_docs/version-0.9.0/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/black_box_fns.md rename to docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md diff --git a/docs/versioned_docs/version-0.6.0/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/cryptographic_primitives.md rename to docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives.md diff --git a/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/00_hashes.mdx new file mode 100644 index 00000000000..2cc3cd81e4e --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/00_hashes.mdx @@ -0,0 +1,146 @@ +--- +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 + +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.17.0/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/01_scalar.mdx new file mode 100644 index 00000000000..c7eed820a80 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/02_schnorr.mdx new file mode 100644 index 00000000000..c184ce28120 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..72bce984821 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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-0.9.0/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/04_ec_primitives.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/cryptographic_primitives/04_ec_primitives.md rename to docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/04_ec_primitives.md diff --git a/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.17.0/standard_library/cryptographic_primitives/05_eddsa.mdx new file mode 100644 index 00000000000..9a5beb55ee9 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/standard_library/logging.md b/docs/versioned_docs/version-v0.17.0/standard_library/logging.md new file mode 100644 index 00000000000..7e2fd9b9aff --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.17.0/standard_library/merkle_trees.md new file mode 100644 index 00000000000..9761105f4f2 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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). + +```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.17.0/standard_library/options.md b/docs/versioned_docs/version-v0.17.0/standard_library/options.md new file mode 100644 index 00000000000..3d3139fb98b --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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.17.0/standard_library/recursion.md b/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md new file mode 100644 index 00000000000..ff4c63acaa7 --- /dev/null +++ b/docs/versioned_docs/version-v0.17.0/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-0.6.0/standard_library/zeroed.md b/docs/versioned_docs/version-v0.17.0/standard_library/zeroed.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/zeroed.md rename to docs/versioned_docs/version-v0.17.0/standard_library/zeroed.md diff --git a/docs/versioned_docs/version-v0.19.1/examples/merkle-proof.mdx b/docs/versioned_docs/version-v0.19.1/examples/merkle-proof.mdx new file mode 100644 index 00000000000..832fb4bb55e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.1/getting_started/00_nargo_installation.md new file mode 100644 index 00000000000..725c5f4d373 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md new file mode 100644 index 00000000000..8b4416beba1 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md new file mode 100644 index 00000000000..9a17f5d6360 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/index.md b/docs/versioned_docs/version-v0.19.1/index.md new file mode 100644 index 00000000000..75e1abf2932 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.19.1/language_concepts/01_functions.md new file mode 100644 index 00000000000..47cdea0cf04 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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 : 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/versioned_docs/version-v0.19.1/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.19.1/language_concepts/02_control_flow.md new file mode 100644 index 00000000000..a7f85360197 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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-0.9.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/language_concepts/03_ops.md rename to docs/versioned_docs/version-v0.19.1/language_concepts/03_ops.md diff --git a/docs/versioned_docs/version-v0.19.1/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.19.1/language_concepts/04_assert.md new file mode 100644 index 00000000000..7427ec6cc63 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.19.1/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.19.1/language_concepts/05_unconstrained.md new file mode 100644 index 00000000000..6b621eda3eb --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/05_unconstrained.md @@ -0,0 +1,96 @@ +--- +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] +--- + + + +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/versioned_docs/version-v0.19.1/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.19.1/language_concepts/06_generics.md new file mode 100644 index 00000000000..9fb4177c2a8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). 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 new file mode 100644 index 00000000000..4641521b1d9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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() -> 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.1/language_concepts/08_lambdas.md b/docs/versioned_docs/version-v0.19.1/language_concepts/08_lambdas.md new file mode 100644 index 00000000000..ae1e6aecab1 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.19.1/language_concepts/09_comments.md b/docs/versioned_docs/version-v0.19.1/language_concepts/09_comments.md new file mode 100644 index 00000000000..3bb4d2f25a4 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/09_comments.md @@ -0,0 +1,32 @@ +--- +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 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/versioned_docs/version-v0.19.1/language_concepts/10_distinct.md b/docs/versioned_docs/version-v0.19.1/language_concepts/10_distinct.md new file mode 100644 index 00000000000..e7ff7f5017a --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/10_distinct.md @@ -0,0 +1,63 @@ +--- +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 `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/versioned_docs/version-v0.19.1/language_concepts/11_shadowing.md b/docs/versioned_docs/version-v0.19.1/language_concepts/11_shadowing.md new file mode 100644 index 00000000000..efd743e764f --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/language_concepts/11_shadowing.md @@ -0,0 +1,43 @@ +--- +title: Shadowing +--- + +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/versioned_docs/version-v0.19.1/language_concepts/data_types.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types.md new file mode 100644 index 00000000000..d546cc463a8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/00_fields.md new file mode 100644 index 00000000000..658a0441ffb --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/language_concepts/data_types/01_integers.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/01_integers.md new file mode 100644 index 00000000000..b1e7ad11bfd --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md new file mode 100644 index 00000000000..885db167d83 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md new file mode 100644 index 00000000000..c42f34ec3ad --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md new file mode 100644 index 00000000000..bdbd1798bef --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/language_concepts/data_types/05_slices.mdx b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/05_slices.mdx new file mode 100644 index 00000000000..1be0ec4a137 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/language_concepts/data_types/06_vectors.mdx b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/06_vectors.mdx new file mode 100644 index 00000000000..4617e90d038 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/language_concepts/data_types/07_tuples.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/07_tuples.md new file mode 100644 index 00000000000..5f6cab974a8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/language_concepts/data_types/08_structs.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/08_structs.md new file mode 100644 index 00000000000..35421734639 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/language_concepts/data_types/09_references.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/09_references.md new file mode 100644 index 00000000000..b0c35ce2cb9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/language_concepts/data_types/10_function_types.md b/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/10_function_types.md new file mode 100644 index 00000000000..1ec92efd594 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/migration_notes.md b/docs/versioned_docs/version-v0.19.1/migration_notes.md new file mode 100644 index 00000000000..e87eb1feaba --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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: , 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.1/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.19.1/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..fb83a33d94e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..75f95aaa305 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.19.1/modules_packages_crates/modules.md new file mode 100644 index 00000000000..147c9b284e8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.19.1/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..d9ac92667c9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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/versioned_docs/version-v0.19.1/nargo/01_commands.md b/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md new file mode 100644 index 00000000000..65e2bdb44e3 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.1/nargo/02_testing.md new file mode 100644 index 00000000000..da767274efd --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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-0.9.0/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.19.1/nargo/03_solidity_verifier.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/nargo/03_solidity_verifier.md rename to docs/versioned_docs/version-v0.19.1/nargo/03_solidity_verifier.md diff --git a/docs/versioned_docs/version-v0.19.1/nargo/04_language_server.md b/docs/versioned_docs/version-v0.19.1/nargo/04_language_server.md new file mode 100644 index 00000000000..48c01465f6e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/getting_started/01_tiny_noir_app.md b/docs/versioned_docs/version-v0.19.1/noir_js/getting_started/01_tiny_noir_app.md new file mode 100644 index 00000000000..c51ed61de52 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/noir_js.md b/docs/versioned_docs/version-v0.19.1/noir_js/noir_js.md new file mode 100644 index 00000000000..f895b22eaf8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 00000000000..5cbe9421b92 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/index.md new file mode 100644 index 00000000000..3680ba3ca77 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/backend_barretenberg/interfaces/Backend.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/interfaces/Backend.md new file mode 100644 index 00000000000..3eb9645c8d2 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 00000000000..266ade75d17 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md new file mode 100644 index 00000000000..34e0dd04205 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md new file mode 100644 index 00000000000..4aeff73d3e4 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.19.1/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 00000000000..04e662c845f --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/.nojekyll b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/classes/Noir.md new file mode 100644 index 00000000000..a8a0bb451c1 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/functions/and.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..0ba5783f0d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/keccak256.md new file mode 100644 index 00000000000..d10f155ce86 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/functions/sha256.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/sha256.md new file mode 100644 index 00000000000..6ba4ecac022 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/index.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/index.md new file mode 100644 index 00000000000..58902c17b99 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md new file mode 100644 index 00000000000..34e0dd04205 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/type-aliases/ProofData.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/ProofData.md new file mode 100644 index 00000000000..4aeff73d3e4 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/noir_js/reference/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.19.1/noir_js/reference/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..c18318850d0 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md new file mode 100644 index 00000000000..1dfabfe8f22 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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-0.7.1/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/cryptographic_primitives.md rename to docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives.md diff --git a/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/00_hashes.mdx new file mode 100644 index 00000000000..76745196681 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/01_scalar.mdx new file mode 100644 index 00000000000..c7eed820a80 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/02_schnorr.mdx new file mode 100644 index 00000000000..c184ce28120 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..72bce984821 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.19.1/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/04_ec_primitives.md new file mode 100644 index 00000000000..6e6b19b6861 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/04_ec_primitives.md @@ -0,0 +1,101 @@ +--- +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 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.19.1/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.19.1/standard_library/cryptographic_primitives/05_eddsa.mdx new file mode 100644 index 00000000000..9a5beb55ee9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/standard_library/logging.md b/docs/versioned_docs/version-v0.19.1/standard_library/logging.md new file mode 100644 index 00000000000..7e2fd9b9aff --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.19.1/standard_library/merkle_trees.md new file mode 100644 index 00000000000..dc383a1426b --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/standard_library/options.md b/docs/versioned_docs/version-v0.19.1/standard_library/options.md new file mode 100644 index 00000000000..3d3139fb98b --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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.1/standard_library/recursion.md b/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md new file mode 100644 index 00000000000..ff4c63acaa7 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.1/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-0.7.1/standard_library/zeroed.md b/docs/versioned_docs/version-v0.19.1/standard_library/zeroed.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/zeroed.md rename to docs/versioned_docs/version-v0.19.1/standard_library/zeroed.md diff --git a/docs/versioned_docs/version-v0.19.2/examples/merkle-proof.mdx b/docs/versioned_docs/version-v0.19.2/examples/merkle-proof.mdx new file mode 100644 index 00000000000..832fb4bb55e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.19.2/getting_started/00_nargo_installation.md new file mode 100644 index 00000000000..725c5f4d373 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md new file mode 100644 index 00000000000..8b4416beba1 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md new file mode 100644 index 00000000000..9a17f5d6360 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/index.md b/docs/versioned_docs/version-v0.19.2/index.md new file mode 100644 index 00000000000..75e1abf2932 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.19.2/language_concepts/01_functions.md new file mode 100644 index 00000000000..47cdea0cf04 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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 : 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/versioned_docs/version-v0.19.2/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.19.2/language_concepts/02_control_flow.md new file mode 100644 index 00000000000..a7f85360197 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.19.2/language_concepts/03_ops.md new file mode 100644 index 00000000000..da02b126059 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.19.2/language_concepts/04_assert.md new file mode 100644 index 00000000000..7427ec6cc63 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.19.2/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.19.2/language_concepts/05_unconstrained.md new file mode 100644 index 00000000000..6b621eda3eb --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/05_unconstrained.md @@ -0,0 +1,96 @@ +--- +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] +--- + + + +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/versioned_docs/version-v0.19.2/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.19.2/language_concepts/06_generics.md new file mode 100644 index 00000000000..9fb4177c2a8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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/tooling/nargo_cli/tests/execution_success/generics/src/main.nr). 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 new file mode 100644 index 00000000000..4641521b1d9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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() -> 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.2/language_concepts/08_lambdas.md b/docs/versioned_docs/version-v0.19.2/language_concepts/08_lambdas.md new file mode 100644 index 00000000000..ae1e6aecab1 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.19.2/language_concepts/09_comments.md b/docs/versioned_docs/version-v0.19.2/language_concepts/09_comments.md new file mode 100644 index 00000000000..3bb4d2f25a4 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/09_comments.md @@ -0,0 +1,32 @@ +--- +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 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/versioned_docs/version-v0.19.2/language_concepts/10_distinct.md b/docs/versioned_docs/version-v0.19.2/language_concepts/10_distinct.md new file mode 100644 index 00000000000..e7ff7f5017a --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/10_distinct.md @@ -0,0 +1,63 @@ +--- +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 `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/versioned_docs/version-v0.19.2/language_concepts/11_shadowing.md b/docs/versioned_docs/version-v0.19.2/language_concepts/11_shadowing.md new file mode 100644 index 00000000000..efd743e764f --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/language_concepts/11_shadowing.md @@ -0,0 +1,43 @@ +--- +title: Shadowing +--- + +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/versioned_docs/version-v0.19.2/language_concepts/data_types.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types.md new file mode 100644 index 00000000000..d546cc463a8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/data_types/00_fields.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/00_fields.md new file mode 100644 index 00000000000..658a0441ffb --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/data_types/01_integers.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/01_integers.md new file mode 100644 index 00000000000..b1e7ad11bfd --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/data_types/02_booleans.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md new file mode 100644 index 00000000000..885db167d83 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/data_types/03_strings.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md new file mode 100644 index 00000000000..c42f34ec3ad --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/data_types/04_arrays.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md new file mode 100644 index 00000000000..bdbd1798bef --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/data_types/05_slices.mdx b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/05_slices.mdx new file mode 100644 index 00000000000..1be0ec4a137 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/data_types/06_vectors.mdx b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/06_vectors.mdx new file mode 100644 index 00000000000..4617e90d038 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/data_types/07_tuples.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/07_tuples.md new file mode 100644 index 00000000000..5f6cab974a8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/data_types/08_structs.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/08_structs.md new file mode 100644 index 00000000000..9255455bdcb --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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. \ No newline at end of file diff --git a/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/09_references.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/09_references.md new file mode 100644 index 00000000000..b0c35ce2cb9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/language_concepts/data_types/10_function_types.md b/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/10_function_types.md new file mode 100644 index 00000000000..1ec92efd594 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/migration_notes.md b/docs/versioned_docs/version-v0.19.2/migration_notes.md new file mode 100644 index 00000000000..e87eb1feaba --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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: , 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.2/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.19.2/modules_packages_crates/crates_and_packages.md new file mode 100644 index 00000000000..fb83a33d94e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md new file mode 100644 index 00000000000..75f95aaa305 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.19.2/modules_packages_crates/modules.md new file mode 100644 index 00000000000..147c9b284e8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/modules_packages_crates/workspaces.md b/docs/versioned_docs/version-v0.19.2/modules_packages_crates/workspaces.md new file mode 100644 index 00000000000..d9ac92667c9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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/versioned_docs/version-v0.19.2/nargo/01_commands.md b/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md new file mode 100644 index 00000000000..65e2bdb44e3 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/nargo/02_testing.md b/docs/versioned_docs/version-v0.19.2/nargo/02_testing.md new file mode 100644 index 00000000000..da767274efd --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.19.2/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.19.2/nargo/03_solidity_verifier.md new file mode 100644 index 00000000000..9ac60cb0ba7 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/nargo/03_solidity_verifier.md @@ -0,0 +1,129 @@ +--- +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.19.2/nargo/04_language_server.md b/docs/versioned_docs/version-v0.19.2/nargo/04_language_server.md new file mode 100644 index 00000000000..48c01465f6e --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/getting_started/01_tiny_noir_app.md b/docs/versioned_docs/version-v0.19.2/noir_js/getting_started/01_tiny_noir_app.md new file mode 100644 index 00000000000..c51ed61de52 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/noir_js.md b/docs/versioned_docs/version-v0.19.2/noir_js/noir_js.md new file mode 100644 index 00000000000..f895b22eaf8 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/backend_barretenberg/.nojekyll b/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 00000000000..5cbe9421b92 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/backend_barretenberg/index.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/index.md new file mode 100644 index 00000000000..3680ba3ca77 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/backend_barretenberg/interfaces/Backend.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/interfaces/Backend.md new file mode 100644 index 00000000000..3eb9645c8d2 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 00000000000..266ade75d17 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/CompiledCircuit.md new file mode 100644 index 00000000000..34e0dd04205 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/type-aliases/ProofData.md new file mode 100644 index 00000000000..4aeff73d3e4 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.19.2/noir_js/reference/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 00000000000..04e662c845f --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/.nojekyll b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/.nojekyll new file mode 100644 index 00000000000..e2ac6616add --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/classes/Noir.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/classes/Noir.md new file mode 100644 index 00000000000..a8a0bb451c1 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/functions/and.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/and.md new file mode 100644 index 00000000000..c783283e396 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/functions/blake2s256.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/blake2s256.md new file mode 100644 index 00000000000..7882d0da8d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 00000000000..0ba5783f0d5 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 00000000000..0b20ff68957 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/functions/keccak256.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/keccak256.md new file mode 100644 index 00000000000..d10f155ce86 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/functions/sha256.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/sha256.md new file mode 100644 index 00000000000..6ba4ecac022 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/functions/xor.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/functions/xor.md new file mode 100644 index 00000000000..8d762b895d3 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/index.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/index.md new file mode 100644 index 00000000000..58902c17b99 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/CompiledCircuit.md new file mode 100644 index 00000000000..34e0dd04205 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 00000000000..812b8b16481 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 00000000000..dd95809186a --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 00000000000..b71fb78a946 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/type-aliases/ProofData.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/ProofData.md new file mode 100644 index 00000000000..4aeff73d3e4 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/type-aliases/WitnessMap.md b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 00000000000..258c46f9d0c --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/noir_js/reference/noir_js/typedoc-sidebar.cjs b/docs/versioned_docs/version-v0.19.2/noir_js/reference/noir_js/typedoc-sidebar.cjs new file mode 100644 index 00000000000..c18318850d0 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md new file mode 100644 index 00000000000..1dfabfe8f22 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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-0.9.0/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/cryptographic_primitives.md rename to docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives.md diff --git a/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/00_hashes.mdx new file mode 100644 index 00000000000..76745196681 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/01_scalar.mdx new file mode 100644 index 00000000000..c7eed820a80 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/02_schnorr.mdx new file mode 100644 index 00000000000..c184ce28120 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx b/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx new file mode 100644 index 00000000000..72bce984821 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.19.2/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/04_ec_primitives.md new file mode 100644 index 00000000000..6e6b19b6861 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/04_ec_primitives.md @@ -0,0 +1,101 @@ +--- +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 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.19.2/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.19.2/standard_library/cryptographic_primitives/05_eddsa.mdx new file mode 100644 index 00000000000..9a5beb55ee9 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/standard_library/logging.md b/docs/versioned_docs/version-v0.19.2/standard_library/logging.md new file mode 100644 index 00000000000..7e2fd9b9aff --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.19.2/standard_library/merkle_trees.md new file mode 100644 index 00000000000..dc383a1426b --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/standard_library/options.md b/docs/versioned_docs/version-v0.19.2/standard_library/options.md new file mode 100644 index 00000000000..3d3139fb98b --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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.2/standard_library/recursion.md b/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md new file mode 100644 index 00000000000..ff4c63acaa7 --- /dev/null +++ b/docs/versioned_docs/version-v0.19.2/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-0.9.0/standard_library/zeroed.md b/docs/versioned_docs/version-v0.19.2/standard_library/zeroed.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/zeroed.md rename to docs/versioned_docs/version-v0.19.2/standard_library/zeroed.md diff --git a/docs/versioned_docs/version-0.6.0/examples/merkle-proof.md b/docs/versioned_docs/version-v0.6.0/examples/merkle-proof.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/examples/merkle-proof.md rename to docs/versioned_docs/version-v0.6.0/examples/merkle-proof.md diff --git a/docs/versioned_docs/version-0.6.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/getting_started/00_nargo_installation.md rename to docs/versioned_docs/version-v0.6.0/getting_started/00_nargo_installation.md diff --git a/docs/versioned_docs/version-0.6.0/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.6.0/getting_started/01_hello_world.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/getting_started/01_hello_world.md rename to docs/versioned_docs/version-v0.6.0/getting_started/01_hello_world.md diff --git a/docs/versioned_docs/version-0.6.0/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.6.0/getting_started/02_breakdown.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/getting_started/02_breakdown.md rename to docs/versioned_docs/version-v0.6.0/getting_started/02_breakdown.md diff --git a/docs/versioned_docs/version-0.6.0/index.md b/docs/versioned_docs/version-v0.6.0/index.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/index.md rename to docs/versioned_docs/version-v0.6.0/index.md diff --git a/docs/versioned_docs/version-0.6.0/language_concepts/00_data_types.md b/docs/versioned_docs/version-v0.6.0/language_concepts/00_data_types.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/language_concepts/00_data_types.md rename to docs/versioned_docs/version-v0.6.0/language_concepts/00_data_types.md diff --git a/docs/versioned_docs/version-0.6.0/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.6.0/language_concepts/01_functions.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/language_concepts/01_functions.md rename to docs/versioned_docs/version-v0.6.0/language_concepts/01_functions.md diff --git a/docs/versioned_docs/version-0.6.0/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.6.0/language_concepts/02_control_flow.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/language_concepts/02_control_flow.md rename to docs/versioned_docs/version-v0.6.0/language_concepts/02_control_flow.md diff --git a/docs/versioned_docs/version-0.6.0/language_concepts/03_ops.md b/docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/language_concepts/03_ops.md rename to docs/versioned_docs/version-v0.6.0/language_concepts/03_ops.md diff --git a/docs/versioned_docs/version-0.6.0/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.6.0/language_concepts/04_assert.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/language_concepts/04_assert.md rename to docs/versioned_docs/version-v0.6.0/language_concepts/04_assert.md diff --git a/docs/versioned_docs/version-0.6.0/language_concepts/05_constrain.md b/docs/versioned_docs/version-v0.6.0/language_concepts/05_constrain.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/language_concepts/05_constrain.md rename to docs/versioned_docs/version-v0.6.0/language_concepts/05_constrain.md diff --git a/docs/versioned_docs/version-0.6.0/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.6.0/language_concepts/06_generics.md similarity index 96% rename from docs/versioned_docs/version-0.6.0/language_concepts/06_generics.md rename to docs/versioned_docs/version-v0.6.0/language_concepts/06_generics.md index 6976666b23e..4d6c01fd797 100644 --- a/docs/versioned_docs/version-0.6.0/language_concepts/06_generics.md +++ b/docs/versioned_docs/version-v0.6.0/language_concepts/06_generics.md @@ -113,4 +113,4 @@ fn main() { ``` 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). +[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-0.6.0/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.6.0/language_concepts/07_mutability.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/language_concepts/07_mutability.md rename to docs/versioned_docs/version-v0.6.0/language_concepts/07_mutability.md diff --git a/docs/versioned_docs/version-0.6.0/language_concepts/08_comments.md b/docs/versioned_docs/version-v0.6.0/language_concepts/08_comments.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/language_concepts/08_comments.md rename to docs/versioned_docs/version-v0.6.0/language_concepts/08_comments.md diff --git a/docs/versioned_docs/version-0.6.0/language_concepts/09_distinct.md b/docs/versioned_docs/version-v0.6.0/language_concepts/09_distinct.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/language_concepts/09_distinct.md rename to docs/versioned_docs/version-v0.6.0/language_concepts/09_distinct.md diff --git a/docs/versioned_docs/version-0.6.0/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.6.0/modules_packages_crates/crates_and_packages.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/modules_packages_crates/crates_and_packages.md rename to docs/versioned_docs/version-v0.6.0/modules_packages_crates/crates_and_packages.md diff --git a/docs/versioned_docs/version-0.6.0/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.6.0/modules_packages_crates/dependencies.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/modules_packages_crates/dependencies.md rename to docs/versioned_docs/version-v0.6.0/modules_packages_crates/dependencies.md diff --git a/docs/versioned_docs/version-0.6.0/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.6.0/modules_packages_crates/modules.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/modules_packages_crates/modules.md rename to docs/versioned_docs/version-v0.6.0/modules_packages_crates/modules.md diff --git a/docs/versioned_docs/version-0.6.0/nargo/01_commands.md b/docs/versioned_docs/version-v0.6.0/nargo/01_commands.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/nargo/01_commands.md rename to docs/versioned_docs/version-v0.6.0/nargo/01_commands.md diff --git a/docs/versioned_docs/version-0.6.0/nargo/02_testing.md b/docs/versioned_docs/version-v0.6.0/nargo/02_testing.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/nargo/02_testing.md rename to docs/versioned_docs/version-v0.6.0/nargo/02_testing.md diff --git a/docs/versioned_docs/version-0.6.0/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.6.0/nargo/03_solidity_verifier.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/nargo/03_solidity_verifier.md rename to docs/versioned_docs/version-v0.6.0/nargo/03_solidity_verifier.md diff --git a/docs/versioned_docs/version-0.6.0/standard_library/array_methods.md b/docs/versioned_docs/version-v0.6.0/standard_library/array_methods.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/array_methods.md rename to docs/versioned_docs/version-v0.6.0/standard_library/array_methods.md diff --git a/docs/versioned_docs/version-0.6.0/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.6.0/standard_library/black_box_fns.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/black_box_fns.md rename to docs/versioned_docs/version-v0.6.0/standard_library/black_box_fns.md diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives.md b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives.md new file mode 100644 index 00000000000..2df4f929474 --- /dev/null +++ b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives.md @@ -0,0 +1,14 @@ +--- +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-0.6.0/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/00_hashes.mdx similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/cryptographic_primitives/00_hashes.mdx rename to docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/00_hashes.mdx diff --git a/docs/versioned_docs/version-0.6.0/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/01_scalar.mdx similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/cryptographic_primitives/01_scalar.mdx rename to docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/01_scalar.mdx diff --git a/docs/versioned_docs/version-0.6.0/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/02_schnorr.mdx similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/cryptographic_primitives/02_schnorr.mdx rename to docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/02_schnorr.mdx diff --git a/docs/versioned_docs/version-0.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 similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx rename to docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx diff --git a/docs/versioned_docs/version-0.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 similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/cryptographic_primitives/04_ec_primitives.md rename to docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/04_ec_primitives.md diff --git a/docs/versioned_docs/version-0.6.0/standard_library/cryptographic_primitives/common/_blackbox.mdx b/docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/common/_blackbox.mdx similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/cryptographic_primitives/common/_blackbox.mdx rename to docs/versioned_docs/version-v0.6.0/standard_library/cryptographic_primitives/common/_blackbox.mdx diff --git a/docs/versioned_docs/version-0.6.0/standard_library/field_methods.md b/docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/field_methods.md rename to docs/versioned_docs/version-v0.6.0/standard_library/field_methods.md diff --git a/docs/versioned_docs/version-0.6.0/standard_library/logging.md b/docs/versioned_docs/version-v0.6.0/standard_library/logging.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/logging.md rename to docs/versioned_docs/version-v0.6.0/standard_library/logging.md diff --git a/docs/versioned_docs/version-0.6.0/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.6.0/standard_library/merkle_trees.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/standard_library/merkle_trees.md rename to docs/versioned_docs/version-v0.6.0/standard_library/merkle_trees.md diff --git a/docs/versioned_docs/version-v0.6.0/standard_library/zeroed.md b/docs/versioned_docs/version-v0.6.0/standard_library/zeroed.md new file mode 100644 index 00000000000..97dab02dac2 --- /dev/null +++ b/docs/versioned_docs/version-v0.6.0/standard_library/zeroed.md @@ -0,0 +1,25 @@ +--- +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-0.6.0/typescript.md b/docs/versioned_docs/version-v0.6.0/typescript.md similarity index 100% rename from docs/versioned_docs/version-0.6.0/typescript.md rename to docs/versioned_docs/version-v0.6.0/typescript.md diff --git a/docs/versioned_docs/version-0.7.1/examples/merkle-proof.md b/docs/versioned_docs/version-v0.7.1/examples/merkle-proof.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/examples/merkle-proof.md rename to docs/versioned_docs/version-v0.7.1/examples/merkle-proof.md diff --git a/docs/versioned_docs/version-0.7.1/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/getting_started/00_nargo_installation.md rename to docs/versioned_docs/version-v0.7.1/getting_started/00_nargo_installation.md diff --git a/docs/versioned_docs/version-0.7.1/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.7.1/getting_started/01_hello_world.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/getting_started/01_hello_world.md rename to docs/versioned_docs/version-v0.7.1/getting_started/01_hello_world.md diff --git a/docs/versioned_docs/version-0.7.1/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.7.1/getting_started/02_breakdown.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/getting_started/02_breakdown.md rename to docs/versioned_docs/version-v0.7.1/getting_started/02_breakdown.md diff --git a/docs/versioned_docs/version-0.7.1/getting_started/03_language_server.md b/docs/versioned_docs/version-v0.7.1/getting_started/03_language_server.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/getting_started/03_language_server.md rename to docs/versioned_docs/version-v0.7.1/getting_started/03_language_server.md diff --git a/docs/versioned_docs/version-0.7.1/index.md b/docs/versioned_docs/version-v0.7.1/index.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/index.md rename to docs/versioned_docs/version-v0.7.1/index.md diff --git a/docs/versioned_docs/version-0.7.1/language_concepts/00_data_types.md b/docs/versioned_docs/version-v0.7.1/language_concepts/00_data_types.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/language_concepts/00_data_types.md rename to docs/versioned_docs/version-v0.7.1/language_concepts/00_data_types.md diff --git a/docs/versioned_docs/version-0.7.1/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.7.1/language_concepts/01_functions.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/language_concepts/01_functions.md rename to docs/versioned_docs/version-v0.7.1/language_concepts/01_functions.md diff --git a/docs/versioned_docs/version-0.7.1/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.7.1/language_concepts/02_control_flow.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/language_concepts/02_control_flow.md rename to docs/versioned_docs/version-v0.7.1/language_concepts/02_control_flow.md 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 new file mode 100644 index 00000000000..da02b126059 --- /dev/null +++ b/docs/versioned_docs/version-v0.7.1/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-0.7.1/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.7.1/language_concepts/04_assert.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/language_concepts/04_assert.md rename to docs/versioned_docs/version-v0.7.1/language_concepts/04_assert.md diff --git a/docs/versioned_docs/version-0.7.1/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.7.1/language_concepts/06_generics.md similarity index 96% rename from docs/versioned_docs/version-0.7.1/language_concepts/06_generics.md rename to docs/versioned_docs/version-v0.7.1/language_concepts/06_generics.md index a4c207e09e4..66f2e85e16b 100644 --- a/docs/versioned_docs/version-0.7.1/language_concepts/06_generics.md +++ b/docs/versioned_docs/version-v0.7.1/language_concepts/06_generics.md @@ -113,4 +113,4 @@ fn main() { ``` 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). +[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-0.7.1/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.7.1/language_concepts/07_mutability.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/language_concepts/07_mutability.md rename to docs/versioned_docs/version-v0.7.1/language_concepts/07_mutability.md diff --git a/docs/versioned_docs/version-0.7.1/language_concepts/08_comments.md b/docs/versioned_docs/version-v0.7.1/language_concepts/08_comments.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/language_concepts/08_comments.md rename to docs/versioned_docs/version-v0.7.1/language_concepts/08_comments.md diff --git a/docs/versioned_docs/version-0.7.1/language_concepts/09_distinct.md b/docs/versioned_docs/version-v0.7.1/language_concepts/09_distinct.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/language_concepts/09_distinct.md rename to docs/versioned_docs/version-v0.7.1/language_concepts/09_distinct.md diff --git a/docs/versioned_docs/version-0.7.1/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.7.1/modules_packages_crates/crates_and_packages.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/modules_packages_crates/crates_and_packages.md rename to docs/versioned_docs/version-v0.7.1/modules_packages_crates/crates_and_packages.md diff --git a/docs/versioned_docs/version-0.7.1/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.7.1/modules_packages_crates/dependencies.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/modules_packages_crates/dependencies.md rename to docs/versioned_docs/version-v0.7.1/modules_packages_crates/dependencies.md diff --git a/docs/versioned_docs/version-0.7.1/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.7.1/modules_packages_crates/modules.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/modules_packages_crates/modules.md rename to docs/versioned_docs/version-v0.7.1/modules_packages_crates/modules.md diff --git a/docs/versioned_docs/version-0.7.1/nargo/01_commands.md b/docs/versioned_docs/version-v0.7.1/nargo/01_commands.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/nargo/01_commands.md rename to docs/versioned_docs/version-v0.7.1/nargo/01_commands.md diff --git a/docs/versioned_docs/version-0.7.1/nargo/02_testing.md b/docs/versioned_docs/version-v0.7.1/nargo/02_testing.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/nargo/02_testing.md rename to docs/versioned_docs/version-v0.7.1/nargo/02_testing.md diff --git a/docs/versioned_docs/version-v0.7.1/nargo/03_solidity_verifier.md b/docs/versioned_docs/version-v0.7.1/nargo/03_solidity_verifier.md new file mode 100644 index 00000000000..9ac60cb0ba7 --- /dev/null +++ b/docs/versioned_docs/version-v0.7.1/nargo/03_solidity_verifier.md @@ -0,0 +1,129 @@ +--- +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-0.7.1/standard_library/array_methods.md b/docs/versioned_docs/version-v0.7.1/standard_library/array_methods.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/array_methods.md rename to docs/versioned_docs/version-v0.7.1/standard_library/array_methods.md diff --git a/docs/versioned_docs/version-0.7.1/standard_library/black_box_fns.md b/docs/versioned_docs/version-v0.7.1/standard_library/black_box_fns.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/black_box_fns.md rename to docs/versioned_docs/version-v0.7.1/standard_library/black_box_fns.md 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 new file mode 100644 index 00000000000..2df4f929474 --- /dev/null +++ b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives.md @@ -0,0 +1,14 @@ +--- +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-0.7.1/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/00_hashes.mdx similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/cryptographic_primitives/00_hashes.mdx rename to docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/00_hashes.mdx diff --git a/docs/versioned_docs/version-0.7.1/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/01_scalar.mdx similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/cryptographic_primitives/01_scalar.mdx rename to docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/01_scalar.mdx diff --git a/docs/versioned_docs/version-0.7.1/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/02_schnorr.mdx similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/cryptographic_primitives/02_schnorr.mdx rename to docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/02_schnorr.mdx diff --git a/docs/versioned_docs/version-0.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 similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx rename to docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/03_ecdsa_secp256k1.mdx diff --git a/docs/versioned_docs/version-0.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 similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/cryptographic_primitives/04_ec_primitives.md rename to docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/04_ec_primitives.md diff --git a/docs/versioned_docs/version-0.7.1/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/05_eddsa.mdx similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/cryptographic_primitives/05_eddsa.mdx rename to docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/05_eddsa.mdx diff --git a/docs/versioned_docs/version-0.7.1/standard_library/cryptographic_primitives/common/_blackbox.mdx b/docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/common/_blackbox.mdx similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/cryptographic_primitives/common/_blackbox.mdx rename to docs/versioned_docs/version-v0.7.1/standard_library/cryptographic_primitives/common/_blackbox.mdx diff --git a/docs/versioned_docs/version-0.7.1/standard_library/field_methods.md b/docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/field_methods.md rename to docs/versioned_docs/version-v0.7.1/standard_library/field_methods.md diff --git a/docs/versioned_docs/version-0.7.1/standard_library/logging.md b/docs/versioned_docs/version-v0.7.1/standard_library/logging.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/logging.md rename to docs/versioned_docs/version-v0.7.1/standard_library/logging.md diff --git a/docs/versioned_docs/version-0.7.1/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.7.1/standard_library/merkle_trees.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/standard_library/merkle_trees.md rename to docs/versioned_docs/version-v0.7.1/standard_library/merkle_trees.md diff --git a/docs/versioned_docs/version-v0.7.1/standard_library/zeroed.md b/docs/versioned_docs/version-v0.7.1/standard_library/zeroed.md new file mode 100644 index 00000000000..97dab02dac2 --- /dev/null +++ b/docs/versioned_docs/version-v0.7.1/standard_library/zeroed.md @@ -0,0 +1,25 @@ +--- +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-0.7.1/typescript.md b/docs/versioned_docs/version-v0.7.1/typescript.md similarity index 100% rename from docs/versioned_docs/version-0.7.1/typescript.md rename to docs/versioned_docs/version-v0.7.1/typescript.md 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 new file mode 100644 index 00000000000..6430780817c --- /dev/null +++ b/docs/versioned_docs/version-v0.9.0/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` +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-0.9.0/getting_started/00_nargo_installation.md b/docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/getting_started/00_nargo_installation.md rename to docs/versioned_docs/version-v0.9.0/getting_started/00_nargo_installation.md diff --git a/docs/versioned_docs/version-0.9.0/getting_started/01_hello_world.md b/docs/versioned_docs/version-v0.9.0/getting_started/01_hello_world.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/getting_started/01_hello_world.md rename to docs/versioned_docs/version-v0.9.0/getting_started/01_hello_world.md diff --git a/docs/versioned_docs/version-0.9.0/getting_started/02_breakdown.md b/docs/versioned_docs/version-v0.9.0/getting_started/02_breakdown.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/getting_started/02_breakdown.md rename to docs/versioned_docs/version-v0.9.0/getting_started/02_breakdown.md diff --git a/docs/versioned_docs/version-0.9.0/getting_started/03_language_server.md b/docs/versioned_docs/version-v0.9.0/getting_started/03_language_server.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/getting_started/03_language_server.md rename to docs/versioned_docs/version-v0.9.0/getting_started/03_language_server.md diff --git a/docs/versioned_docs/version-0.9.0/index.md b/docs/versioned_docs/version-v0.9.0/index.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/index.md rename to docs/versioned_docs/version-v0.9.0/index.md diff --git a/docs/versioned_docs/version-0.9.0/language_concepts/00_data_types.md b/docs/versioned_docs/version-v0.9.0/language_concepts/00_data_types.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/language_concepts/00_data_types.md rename to docs/versioned_docs/version-v0.9.0/language_concepts/00_data_types.md diff --git a/docs/versioned_docs/version-0.9.0/language_concepts/01_functions.md b/docs/versioned_docs/version-v0.9.0/language_concepts/01_functions.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/language_concepts/01_functions.md rename to docs/versioned_docs/version-v0.9.0/language_concepts/01_functions.md diff --git a/docs/versioned_docs/version-0.9.0/language_concepts/02_control_flow.md b/docs/versioned_docs/version-v0.9.0/language_concepts/02_control_flow.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/language_concepts/02_control_flow.md rename to docs/versioned_docs/version-v0.9.0/language_concepts/02_control_flow.md 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 new file mode 100644 index 00000000000..da02b126059 --- /dev/null +++ b/docs/versioned_docs/version-v0.9.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/versioned_docs/version-0.9.0/language_concepts/04_assert.md b/docs/versioned_docs/version-v0.9.0/language_concepts/04_assert.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/language_concepts/04_assert.md rename to docs/versioned_docs/version-v0.9.0/language_concepts/04_assert.md diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/05_unconstrained.md b/docs/versioned_docs/version-v0.9.0/language_concepts/05_unconstrained.md new file mode 100644 index 00000000000..6b621eda3eb --- /dev/null +++ b/docs/versioned_docs/version-v0.9.0/language_concepts/05_unconstrained.md @@ -0,0 +1,96 @@ +--- +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] +--- + + + +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/versioned_docs/version-0.9.0/language_concepts/06_generics.md b/docs/versioned_docs/version-v0.9.0/language_concepts/06_generics.md similarity index 96% rename from docs/versioned_docs/version-0.9.0/language_concepts/06_generics.md rename to docs/versioned_docs/version-v0.9.0/language_concepts/06_generics.md index a4c207e09e4..66f2e85e16b 100644 --- a/docs/versioned_docs/version-0.9.0/language_concepts/06_generics.md +++ b/docs/versioned_docs/version-v0.9.0/language_concepts/06_generics.md @@ -113,4 +113,4 @@ fn main() { ``` 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). +[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-0.9.0/language_concepts/07_mutability.md b/docs/versioned_docs/version-v0.9.0/language_concepts/07_mutability.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/language_concepts/07_mutability.md rename to docs/versioned_docs/version-v0.9.0/language_concepts/07_mutability.md diff --git a/docs/versioned_docs/version-v0.9.0/language_concepts/08_comments.md b/docs/versioned_docs/version-v0.9.0/language_concepts/08_comments.md new file mode 100644 index 00000000000..3bb4d2f25a4 --- /dev/null +++ b/docs/versioned_docs/version-v0.9.0/language_concepts/08_comments.md @@ -0,0 +1,32 @@ +--- +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 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/versioned_docs/version-v0.9.0/language_concepts/09_distinct.md b/docs/versioned_docs/version-v0.9.0/language_concepts/09_distinct.md new file mode 100644 index 00000000000..e7ff7f5017a --- /dev/null +++ b/docs/versioned_docs/version-v0.9.0/language_concepts/09_distinct.md @@ -0,0 +1,63 @@ +--- +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 `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/versioned_docs/version-v0.9.0/language_concepts/10_shadowing.md b/docs/versioned_docs/version-v0.9.0/language_concepts/10_shadowing.md new file mode 100644 index 00000000000..efd743e764f --- /dev/null +++ b/docs/versioned_docs/version-v0.9.0/language_concepts/10_shadowing.md @@ -0,0 +1,43 @@ +--- +title: Shadowing +--- + +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/versioned_docs/version-0.9.0/modules_packages_crates/crates_and_packages.md b/docs/versioned_docs/version-v0.9.0/modules_packages_crates/crates_and_packages.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/modules_packages_crates/crates_and_packages.md rename to docs/versioned_docs/version-v0.9.0/modules_packages_crates/crates_and_packages.md diff --git a/docs/versioned_docs/version-0.9.0/modules_packages_crates/dependencies.md b/docs/versioned_docs/version-v0.9.0/modules_packages_crates/dependencies.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/modules_packages_crates/dependencies.md rename to docs/versioned_docs/version-v0.9.0/modules_packages_crates/dependencies.md diff --git a/docs/versioned_docs/version-0.9.0/modules_packages_crates/modules.md b/docs/versioned_docs/version-v0.9.0/modules_packages_crates/modules.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/modules_packages_crates/modules.md rename to docs/versioned_docs/version-v0.9.0/modules_packages_crates/modules.md diff --git a/docs/versioned_docs/version-0.9.0/nargo/01_commands.md b/docs/versioned_docs/version-v0.9.0/nargo/01_commands.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/nargo/01_commands.md rename to docs/versioned_docs/version-v0.9.0/nargo/01_commands.md diff --git a/docs/versioned_docs/version-0.9.0/nargo/02_testing.md b/docs/versioned_docs/version-v0.9.0/nargo/02_testing.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/nargo/02_testing.md rename to docs/versioned_docs/version-v0.9.0/nargo/02_testing.md 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 new file mode 100644 index 00000000000..9ac60cb0ba7 --- /dev/null +++ b/docs/versioned_docs/version-v0.9.0/nargo/03_solidity_verifier.md @@ -0,0 +1,129 @@ +--- +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 new file mode 100644 index 00000000000..c758846b688 --- /dev/null +++ b/docs/versioned_docs/version-v0.9.0/standard_library/black_box_fns.md @@ -0,0 +1,45 @@ +--- +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 new file mode 100644 index 00000000000..2df4f929474 --- /dev/null +++ b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives.md @@ -0,0 +1,14 @@ +--- +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-0.9.0/standard_library/cryptographic_primitives/00_hashes.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/00_hashes.mdx similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/cryptographic_primitives/00_hashes.mdx rename to docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/00_hashes.mdx diff --git a/docs/versioned_docs/version-0.9.0/standard_library/cryptographic_primitives/01_scalar.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/01_scalar.mdx similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/cryptographic_primitives/01_scalar.mdx rename to docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/01_scalar.mdx diff --git a/docs/versioned_docs/version-0.9.0/standard_library/cryptographic_primitives/02_schnorr.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/02_schnorr.mdx similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/cryptographic_primitives/02_schnorr.mdx rename to docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/02_schnorr.mdx diff --git a/docs/versioned_docs/version-0.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 similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx rename to docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/03_ecdsa_sig_verification.mdx diff --git a/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/04_ec_primitives.md b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/04_ec_primitives.md new file mode 100644 index 00000000000..6e6b19b6861 --- /dev/null +++ b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/04_ec_primitives.md @@ -0,0 +1,101 @@ +--- +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 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-0.9.0/standard_library/cryptographic_primitives/05_eddsa.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/05_eddsa.mdx similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/cryptographic_primitives/05_eddsa.mdx rename to docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/05_eddsa.mdx diff --git a/docs/versioned_docs/version-0.9.0/standard_library/cryptographic_primitives/common/_blackbox.mdx b/docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/common/_blackbox.mdx similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/cryptographic_primitives/common/_blackbox.mdx rename to docs/versioned_docs/version-v0.9.0/standard_library/cryptographic_primitives/common/_blackbox.mdx diff --git a/docs/versioned_docs/version-0.9.0/standard_library/field_methods.md b/docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/field_methods.md rename to docs/versioned_docs/version-v0.9.0/standard_library/field_methods.md diff --git a/docs/versioned_docs/version-0.9.0/standard_library/logging.md b/docs/versioned_docs/version-v0.9.0/standard_library/logging.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/logging.md rename to docs/versioned_docs/version-v0.9.0/standard_library/logging.md diff --git a/docs/versioned_docs/version-0.9.0/standard_library/merkle_trees.md b/docs/versioned_docs/version-v0.9.0/standard_library/merkle_trees.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/merkle_trees.md rename to docs/versioned_docs/version-v0.9.0/standard_library/merkle_trees.md diff --git a/docs/versioned_docs/version-0.9.0/standard_library/recursion.md b/docs/versioned_docs/version-v0.9.0/standard_library/recursion.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/recursion.md rename to docs/versioned_docs/version-v0.9.0/standard_library/recursion.md diff --git a/docs/versioned_docs/version-0.9.0/standard_library/slice_methods.md b/docs/versioned_docs/version-v0.9.0/standard_library/slice_methods.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/standard_library/slice_methods.md rename to docs/versioned_docs/version-v0.9.0/standard_library/slice_methods.md 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 new file mode 100644 index 00000000000..97dab02dac2 --- /dev/null +++ b/docs/versioned_docs/version-v0.9.0/standard_library/zeroed.md @@ -0,0 +1,25 @@ +--- +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-0.9.0/typescript.md b/docs/versioned_docs/version-v0.9.0/typescript.md similarity index 100% rename from docs/versioned_docs/version-0.9.0/typescript.md rename to docs/versioned_docs/version-v0.9.0/typescript.md diff --git a/docs/versioned_sidebars/version-0.10.5-sidebars.json b/docs/versioned_sidebars/version-v0.10.5-sidebars.json similarity index 100% rename from docs/versioned_sidebars/version-0.10.5-sidebars.json rename to docs/versioned_sidebars/version-v0.10.5-sidebars.json diff --git a/docs/versioned_sidebars/version-v0.17.0-sidebars.json b/docs/versioned_sidebars/version-v0.17.0-sidebars.json new file mode 100644 index 00000000000..a9ec39925d9 --- /dev/null +++ b/docs/versioned_sidebars/version-v0.17.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.1-sidebars.json b/docs/versioned_sidebars/version-v0.19.1-sidebars.json new file mode 100644 index 00000000000..6823055c5d3 --- /dev/null +++ b/docs/versioned_sidebars/version-v0.19.1-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.2-sidebars.json b/docs/versioned_sidebars/version-v0.19.2-sidebars.json new file mode 100644 index 00000000000..6823055c5d3 --- /dev/null +++ b/docs/versioned_sidebars/version-v0.19.2-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-0.6.0-sidebars.json b/docs/versioned_sidebars/version-v0.6.0-sidebars.json similarity index 100% rename from docs/versioned_sidebars/version-0.6.0-sidebars.json rename to docs/versioned_sidebars/version-v0.6.0-sidebars.json diff --git a/docs/versioned_sidebars/version-0.7.1-sidebars.json b/docs/versioned_sidebars/version-v0.7.1-sidebars.json similarity index 100% rename from docs/versioned_sidebars/version-0.7.1-sidebars.json rename to docs/versioned_sidebars/version-v0.7.1-sidebars.json diff --git a/docs/versioned_sidebars/version-0.9.0-sidebars.json b/docs/versioned_sidebars/version-v0.9.0-sidebars.json similarity index 100% rename from docs/versioned_sidebars/version-0.9.0-sidebars.json rename to docs/versioned_sidebars/version-v0.9.0-sidebars.json diff --git a/docs/versions.json b/docs/versions.json index 26d22536e02..ebd565cb0ae 100644 --- a/docs/versions.json +++ b/docs/versions.json @@ -1,6 +1,5 @@ [ - "0.10.5", - "0.9.0", - "0.7.1", - "0.6.0" + "v0.19.2", + "v0.17.0", + "v0.10.5" ] diff --git a/flake.lock b/flake.lock index e779473f0ec..5a9f9470a1f 100644 --- a/flake.lock +++ b/flake.lock @@ -84,16 +84,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1681269223, - "narHash": "sha256-i6OeI2f7qGvmLfD07l1Az5iBL+bFeP0RHixisWtpUGo=", + "lastModified": 1695559356, + "narHash": "sha256-kXZ1pUoImD9OEbPCwpTz4tHsNTr4CIyIfXb3ocuR8sI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "87edbd74246ccdfa64503f334ed86fa04010bab9", + "rev": "261abe8a44a7e8392598d038d2e01f7b33cf26d0", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-22.11", + "ref": "nixos-23.05", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index 5eeb50a6132..0091a49f240 100644 --- a/flake.nix +++ b/flake.nix @@ -5,7 +5,7 @@ # use so they use the `inputs.*.follows` syntax to reference our inputs inputs = { nixpkgs = { - url = "github:NixOS/nixpkgs/nixos-22.11"; + url = "github:NixOS/nixpkgs/nixos-23.05"; }; flake-utils = { @@ -44,7 +44,7 @@ rustToolchain = fenix.packages.${system}.fromToolchainFile { file = ./rust-toolchain.toml; - sha256 = "sha256-Zk2rxv6vwKFkTTidgjPm6gDsseVmmljVt201H7zuDkk="; + sha256 = "sha256-R0F0Risbr74xg9mEYydyebx/z0Wu6HI0/KWwrV30vZo="; }; craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain; @@ -73,7 +73,7 @@ # Configuration shared between builds config = { # x-release-please-start-version - version = "0.18.0"; + version = "0.19.2"; # x-release-please-end src = pkgs.lib.cleanSourceWith { diff --git a/noir_stdlib/Nargo.toml b/noir_stdlib/Nargo.toml index 9b7a79ad2a6..d2f8ebcb636 100644 --- a/noir_stdlib/Nargo.toml +++ b/noir_stdlib/Nargo.toml @@ -2,6 +2,4 @@ name = "std" type = "lib" authors = [""] -compiler_version = "0.1" - [dependencies] diff --git a/noir_stdlib/src/collections/vec.nr b/noir_stdlib/src/collections/vec.nr index 1c9a791961e..43d68e1d1e7 100644 --- a/noir_stdlib/src/collections/vec.nr +++ b/noir_stdlib/src/collections/vec.nr @@ -1,7 +1,6 @@ struct Vec { slice: [T] } - // A mutable vector type implemented as a wrapper around immutable slices. // A separate type is technically not needed but helps differentiate which operations are mutable. impl Vec { diff --git a/noir_stdlib/src/ec.nr b/noir_stdlib/src/ec.nr index 8b426f46825..86fb201408f 100644 --- a/noir_stdlib/src/ec.nr +++ b/noir_stdlib/src/ec.nr @@ -119,19 +119,15 @@ mod consts; // Commonly used curve presets // // *TODO: Replace Field with Bigint. // **TODO: Support arrays of structs to make this work. - - // Field-dependent constant ZETA = a non-square element of Field // Required for Elligator 2 map // TODO: Replace with built-in constant. global ZETA = 5; - // Field-dependent constants for Tonelli-Shanks algorithm (see sqrt function below) // TODO: Possibly make this built-in. global C1 = 28; global C3 = 40770029410420498293352137776570907027550720424234931066070132305055; global C5 = 19103219067921713944291392827692070036145651957329286315305642004821462161904; - // Higher-order version of scalar multiplication // TODO: Make this work so that the submodules' bit_mul may be defined in terms of it. //fn bit_mul(add: fn(T,T) -> T, e: T, bits: [u1; N], p: T) -> T { @@ -146,39 +142,32 @@ global C5 = 19103219067921713944291392827692070036145651957329286315305642004821 // // out //} - // TODO: Make this built-in. pub fn safe_inverse(x: Field) -> Field { - if x == 0 { - 0 - } else { - 1/x - } + if x == 0 { 0 } else { 1 / x } } - // Boolean indicating whether Field element is a square, i.e. whether there exists a y in Field s.t. x = y*y. pub fn is_square(x: Field) -> bool { - let v = pow(x, 0 - 1/2); + let v = pow(x, 0 - 1 / 2); - v*(v-1) == 0 + v * (v - 1) == 0 } - // Power function of two Field arguments of arbitrary size. // Adapted from std::field::pow_32. -pub fn pow(x: Field, y: Field) -> Field { // As in tests with minor modifications +pub fn pow(x: Field, y: Field) -> Field { + // As in tests with minor modifications let N_BITS = crate::field::modulus_num_bits(); let mut r = 1 as Field; let b = y.to_le_bits(N_BITS as u32); - + for i in 0..N_BITS { r *= r; r *= (b[N_BITS - 1 - i] as Field)*x + (1-b[N_BITS - 1 - i] as Field); } - + r } - // Tonelli-Shanks algorithm for computing the square root of a Field element. // Requires C1 = max{c: 2^c divides (p-1)}, where p is the order of Field // as well as C3 = (C2 - 1)/2, where C2 = (p-1)/(2^c1), @@ -186,27 +175,24 @@ pub fn pow(x: Field, y: Field) -> Field { // As in tests with minor modification // These are pre-computed above as globals. pub fn sqrt(x: Field) -> Field { let mut z = pow(x, C3); - let mut t = z*z*x; + let mut t = z * z * x; z *= x; let mut b = t; let mut c = C5; - - for i in 0..(C1-1) { - - for _j in 1..(C1-i-1) { - + + for i in 0..(C1 - 1) { + for _j in 1..(C1 - i - 1) { b *= b; - } - + z *= if b == 1 { 1 } else { c }; - + c *= c; - + t *= if b == 1 { 1 } else { c }; - + b = t; } - + z } diff --git a/noir_stdlib/src/ec/consts/te.nr b/noir_stdlib/src/ec/consts/te.nr index b5847e77f34..469493a35ee 100644 --- a/noir_stdlib/src/ec/consts/te.nr +++ b/noir_stdlib/src/ec/consts/te.nr @@ -8,26 +8,19 @@ struct BabyJubjub { suborder: Field, } +#[field(bn254)] pub fn baby_jubjub() -> BabyJubjub { - assert(compat::is_bn254()); - 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, + suborder: 2736030358979909402780800718157159386076813972158567259200215660948447373041 } } diff --git a/noir_stdlib/src/ec/montcurve.nr b/noir_stdlib/src/ec/montcurve.nr index 6a57f258c8e..82d22837b46 100644 --- a/noir_stdlib/src/ec/montcurve.nr +++ b/noir_stdlib/src/ec/montcurve.nr @@ -12,7 +12,6 @@ mod affine { use crate::ec::safe_inverse; use crate::ec::sqrt; use crate::ec::ZETA; - // Curve specification struct Curve { // Montgomery Curve configuration (ky^2 = x^3 + j*x^2 + x) j: Field, @@ -20,7 +19,6 @@ mod affine { // Generator as point in Cartesian coordinates gen: Point } - // Point in Cartesian coordinates struct Point { x: Field, @@ -228,7 +226,6 @@ mod curvegroup { // Generator as point in projective coordinates gen: Point } - // Point in projective coordinates struct Point { x: Field, diff --git a/noir_stdlib/src/ec/swcurve.nr b/noir_stdlib/src/ec/swcurve.nr index 4aa210f6df3..e9b6f661843 100644 --- a/noir_stdlib/src/ec/swcurve.nr +++ b/noir_stdlib/src/ec/swcurve.nr @@ -7,7 +7,6 @@ mod affine { use crate::ec::safe_inverse; use crate::ec::is_square; use crate::ec::sqrt; - // Curve specification struct Curve { // Short Weierstraß curve // Coefficients in defining equation y^2 = x^3 + ax + b @@ -16,7 +15,6 @@ mod affine { // Generator as point in Cartesian coordinates gen: Point } - // Point in Cartesian coordinates struct Point { x: Field, @@ -184,7 +182,6 @@ mod curvegroup { // Points are represented by three-dimensional Jacobian coordinates. // See for details. use crate::ec::swcurve::affine; - // Curve specification struct Curve { // Short Weierstraß curve // Coefficients in defining equation y^2 = x^3 + axz^4 + bz^6 @@ -193,7 +190,6 @@ mod curvegroup { // Generator as point in Cartesian coordinates gen: Point } - // Point in three-dimensional Jacobian coordinates struct Point { x: Field, diff --git a/noir_stdlib/src/ec/tecurve.nr b/noir_stdlib/src/ec/tecurve.nr index 54b59e99a54..849b45ff012 100644 --- a/noir_stdlib/src/ec/tecurve.nr +++ b/noir_stdlib/src/ec/tecurve.nr @@ -9,7 +9,6 @@ mod affine { use crate::ec::montcurve::affine::Point as MPoint; use crate::ec::swcurve::affine::Curve as SWCurve; use crate::ec::swcurve::affine::Point as SWPoint; - // Curve specification struct Curve { // Twisted Edwards curve // Coefficients in defining equation ax^2 + y^2 = 1 + dx^2y^2 @@ -18,7 +17,6 @@ mod affine { // Generator as point in Cartesian coordinates gen: Point } - // Point in Cartesian coordinates struct Point { x: Field, @@ -76,7 +74,6 @@ mod affine { } } - impl Curve { // Curve constructor pub fn new(a: Field, d: Field, gen: Point) -> Curve { @@ -201,7 +198,6 @@ mod curvegroup { use crate::ec::montcurve::curvegroup::Point as MPoint; use crate::ec::swcurve::curvegroup::Curve as SWCurve; use crate::ec::swcurve::curvegroup::Point as SWPoint; - // Curve specification struct Curve { // Twisted Edwards curve // Coefficients in defining equation a(x^2 + y^2)z^2 = z^4 + dx^2y^2 @@ -210,7 +206,6 @@ mod curvegroup { // Generator as point in projective coordinates gen: Point } - // Point in extended twisted Edwards coordinates struct Point { x: Field, diff --git a/noir_stdlib/src/ecdsa_secp256k1.nr b/noir_stdlib/src/ecdsa_secp256k1.nr index 1ad25811b8a..61687f557fe 100644 --- a/noir_stdlib/src/ecdsa_secp256k1.nr +++ b/noir_stdlib/src/ecdsa_secp256k1.nr @@ -1,2 +1,2 @@ #[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 b47b69fa276..7af37407edd 100644 --- a/noir_stdlib/src/ecdsa_secp256r1.nr +++ b/noir_stdlib/src/ecdsa_secp256r1.nr @@ -1,2 +1,2 @@ #[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/eddsa.nr b/noir_stdlib/src/eddsa.nr index ff8c1da1397..39051e23233 100644 --- a/noir_stdlib/src/eddsa.nr +++ b/noir_stdlib/src/eddsa.nr @@ -1,7 +1,6 @@ use crate::hash::poseidon; use crate::ec::consts::te::baby_jubjub; use crate::ec::tecurve::affine::Point as TEPoint; - // Returns true if x is less than y fn lt_bytes32(x: Field, y: Field) -> bool { let x_bytes = x.to_le_bytes(32); @@ -21,7 +20,6 @@ fn lt_bytes32(x: Field, y: Field) -> bool { } x_is_lt } - // Returns true if signature is valid pub fn eddsa_poseidon_verify( pub_key_x: Field, @@ -29,11 +27,10 @@ pub fn eddsa_poseidon_verify( signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, - message: Field, + message: Field ) -> bool { // Verifies by testing: // S * B8 = R8 + H(R8, A, m) * A8 - let bjj = baby_jubjub(); let pub_key = TEPoint::new(pub_key_x, pub_key_y); @@ -41,32 +38,19 @@ pub fn eddsa_poseidon_verify( let signature_r8 = TEPoint::new(signature_r8_x, signature_r8_y); assert(bjj.curve.contains(signature_r8)); - // Ensure S < Subgroup Order assert(lt_bytes32(signature_s, bjj.suborder)); - // Calculate the h = H(R, A, msg) - let hash: Field = poseidon::bn254::hash_5([ - signature_r8_x, - signature_r8_y, - pub_key_x, - pub_key_y, - message, - ]); - + let hash: Field = poseidon::bn254::hash_5([signature_r8_x, signature_r8_y, pub_key_x, pub_key_y, message]); // Calculate second part of the right side: right2 = h*8*A - // Multiply by 8 by doubling 3 times. This also ensures that the result is in the subgroup. let pub_key_mul_2 = bjj.curve.add(pub_key, pub_key); let pub_key_mul_4 = bjj.curve.add(pub_key_mul_2, pub_key_mul_2); let pub_key_mul_8 = bjj.curve.add(pub_key_mul_4, pub_key_mul_4); - // We check that A8 is not zero. assert(!pub_key_mul_8.is_zero()); - // Compute the right side: R8 + h * A8 let right = bjj.curve.add(signature_r8, bjj.curve.mul(hash, pub_key_mul_8)); - // Calculate left side of equation left = S * B8 let left = bjj.curve.mul(signature_s, bjj.base8); diff --git a/noir_stdlib/src/field.nr b/noir_stdlib/src/field.nr index 3959f1ea175..b4cb9b64e3c 100644 --- a/noir_stdlib/src/field.nr +++ b/noir_stdlib/src/field.nr @@ -1,4 +1,3 @@ - impl Field { pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] { crate::assert_constant(bit_size); @@ -82,3 +81,18 @@ pub fn modulus_be_bytes() -> [u8] {} #[builtin(modulus_le_bytes)] pub fn modulus_le_bytes() -> [u8] {} +// Convert a 32 byte array to a field element +pub fn bytes32_to_field(bytes32: [u8; 32]) -> Field { + // Convert it to a field element + let mut v = 1; + let mut high = 0 as Field; + let mut low = 0 as Field; + + for i in 0..16 { + high = high + (bytes32[15 - i] as Field) * v; + low = low + (bytes32[16 + 15 - i] as Field) * v; + v = v * 256; + } + // Abuse that a % p + b % p = (a + b) % p and that low < p + low + high * v +} diff --git a/noir_stdlib/src/hash.nr b/noir_stdlib/src/hash.nr index 1d05f0462f5..879345dd686 100644 --- a/noir_stdlib/src/hash.nr +++ b/noir_stdlib/src/hash.nr @@ -1,156 +1,53 @@ mod poseidon; +mod mimc; #[foreign(sha256)] -pub fn sha256(_input : [u8; N]) -> [u8; 32] {} +pub fn sha256(_input: [u8; N]) -> [u8; 32] {} #[foreign(blake2s)] -pub fn blake2s(_input : [u8; N]) -> [u8; 32] {} +pub fn blake2s(_input: [u8; N]) -> [u8; 32] {} #[foreign(blake3)] pub fn blake3(_input : [u8; N]) -> [u8; 32] {} -pub fn pedersen(input : [Field; N]) -> [Field; 2] { - pedersen_with_separator(input, 0) +struct PedersenPoint { + x : Field, + y : Field, +} + +pub fn pedersen_commitment(input: [Field; N]) -> PedersenPoint { + pedersen_commitment_with_separator(input, 0) } #[foreign(pedersen)] -pub fn pedersen_with_separator(_input : [Field; N], _separator : u32) -> [Field; 2] {} +pub fn __pedersen_commitment_with_separator(_input: [Field; N], _separator: u32) -> [Field; 2] {} -pub fn pedersen_hash(input : [Field; N]) -> Field { +pub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> PedersenPoint { + let values = __pedersen_commitment_with_separator(input, separator); + PedersenPoint { x: values[0], y: values[1] } +} + +pub fn pedersen_hash(input: [Field; N]) -> Field { pedersen_hash_with_separator(input, 0) } #[foreign(pedersen_hash)] -pub fn pedersen_hash_with_separator(_input : [Field; N], _separator : u32) -> Field {} +pub fn pedersen_hash_with_separator(_input: [Field; N], _separator: u32) -> Field {} -#[foreign(hash_to_field_128_security)] -pub fn hash_to_field(_input : [Field; N]) -> Field {} +pub fn hash_to_field(_input: [Field; N]) -> Field { + let mut inputs_as_bytes = []; -#[foreign(keccak256)] -pub fn keccak256(_input : [u8; N], _message_size: u32) -> [u8; 32] {} + for i in 0..N { + let input_bytes = _input[i].to_le_bytes(32); + for i in 0..32 { + inputs_as_bytes = inputs_as_bytes.push_back(input_bytes[i]); + } + } -// mimc-p/p implementation -// constants are (publicly generated) random numbers, for instance using keccak as a ROM. -// You must use constants generated for the native field -// Rounds number should be ~ log(p)/log(exp) -// For 254 bit primes, exponent 7 and 91 rounds seems to be recommended -fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field { - //round 0 - let mut t = x + k; - let mut h = t.pow_32(exp); - //next rounds - for i in 1 .. constants.len() { - t = h + k + constants[i]; - h = t.pow_32(exp); - }; - h + k + let hashed_input = blake2s(inputs_as_bytes); + crate::field::bytes32_to_field(hashed_input) } -global MIMC_BN254_ROUNDS = 91; - -//mimc implementation with hardcoded parameters for BN254 curve. -pub fn mimc_bn254(array: [Field; N]) -> Field { - //mimc parameters - let exponent = 7; - //generated from seed "mimc" using keccak256 - let constants: [Field; MIMC_BN254_ROUNDS] = [ - 0, - 20888961410941983456478427210666206549300505294776164667214940546594746570981, - 15265126113435022738560151911929040668591755459209400716467504685752745317193, - 8334177627492981984476504167502758309043212251641796197711684499645635709656, - 1374324219480165500871639364801692115397519265181803854177629327624133579404, - 11442588683664344394633565859260176446561886575962616332903193988751292992472, - 2558901189096558760448896669327086721003508630712968559048179091037845349145, - 11189978595292752354820141775598510151189959177917284797737745690127318076389, - 3262966573163560839685415914157855077211340576201936620532175028036746741754, - 17029914891543225301403832095880481731551830725367286980611178737703889171730, - 4614037031668406927330683909387957156531244689520944789503628527855167665518, - 19647356996769918391113967168615123299113119185942498194367262335168397100658, - 5040699236106090655289931820723926657076483236860546282406111821875672148900, - 2632385916954580941368956176626336146806721642583847728103570779270161510514, - 17691411851977575435597871505860208507285462834710151833948561098560743654671, - 11482807709115676646560379017491661435505951727793345550942389701970904563183, - 8360838254132998143349158726141014535383109403565779450210746881879715734773, - 12663821244032248511491386323242575231591777785787269938928497649288048289525, - 3067001377342968891237590775929219083706800062321980129409398033259904188058, - 8536471869378957766675292398190944925664113548202769136103887479787957959589, - 19825444354178182240559170937204690272111734703605805530888940813160705385792, - 16703465144013840124940690347975638755097486902749048533167980887413919317592, - 13061236261277650370863439564453267964462486225679643020432589226741411380501, - 10864774797625152707517901967943775867717907803542223029967000416969007792571, - 10035653564014594269791753415727486340557376923045841607746250017541686319774, - 3446968588058668564420958894889124905706353937375068998436129414772610003289, - 4653317306466493184743870159523234588955994456998076243468148492375236846006, - 8486711143589723036499933521576871883500223198263343024003617825616410932026, - 250710584458582618659378487568129931785810765264752039738223488321597070280, - 2104159799604932521291371026105311735948154964200596636974609406977292675173, - 16313562605837709339799839901240652934758303521543693857533755376563489378839, - 6032365105133504724925793806318578936233045029919447519826248813478479197288, - 14025118133847866722315446277964222215118620050302054655768867040006542798474, - 7400123822125662712777833064081316757896757785777291653271747396958201309118, - 1744432620323851751204287974553233986555641872755053103823939564833813704825, - 8316378125659383262515151597439205374263247719876250938893842106722210729522, - 6739722627047123650704294650168547689199576889424317598327664349670094847386, - 21211457866117465531949733809706514799713333930924902519246949506964470524162, - 13718112532745211817410303291774369209520657938741992779396229864894885156527, - 5264534817993325015357427094323255342713527811596856940387954546330728068658, - 18884137497114307927425084003812022333609937761793387700010402412840002189451, - 5148596049900083984813839872929010525572543381981952060869301611018636120248, - 19799686398774806587970184652860783461860993790013219899147141137827718662674, - 19240878651604412704364448729659032944342952609050243268894572835672205984837, - 10546185249390392695582524554167530669949955276893453512788278945742408153192, - 5507959600969845538113649209272736011390582494851145043668969080335346810411, - 18177751737739153338153217698774510185696788019377850245260475034576050820091, - 19603444733183990109492724100282114612026332366576932662794133334264283907557, - 10548274686824425401349248282213580046351514091431715597441736281987273193140, - 1823201861560942974198127384034483127920205835821334101215923769688644479957, - 11867589662193422187545516240823411225342068709600734253659804646934346124945, - 18718569356736340558616379408444812528964066420519677106145092918482774343613, - 10530777752259630125564678480897857853807637120039176813174150229243735996839, - 20486583726592018813337145844457018474256372770211860618687961310422228379031, - 12690713110714036569415168795200156516217175005650145422920562694422306200486, - 17386427286863519095301372413760745749282643730629659997153085139065756667205, - 2216432659854733047132347621569505613620980842043977268828076165669557467682, - 6309765381643925252238633914530877025934201680691496500372265330505506717193, - 20806323192073945401862788605803131761175139076694468214027227878952047793390, - 4037040458505567977365391535756875199663510397600316887746139396052445718861, - 19948974083684238245321361840704327952464170097132407924861169241740046562673, - 845322671528508199439318170916419179535949348988022948153107378280175750024, - 16222384601744433420585982239113457177459602187868460608565289920306145389382, - 10232118865851112229330353999139005145127746617219324244541194256766741433339, - 6699067738555349409504843460654299019000594109597429103342076743347235369120, - 6220784880752427143725783746407285094967584864656399181815603544365010379208, - 6129250029437675212264306655559561251995722990149771051304736001195288083309, - 10773245783118750721454994239248013870822765715268323522295722350908043393604, - 4490242021765793917495398271905043433053432245571325177153467194570741607167, - 19596995117319480189066041930051006586888908165330319666010398892494684778526, - 837850695495734270707668553360118467905109360511302468085569220634750561083, - 11803922811376367215191737026157445294481406304781326649717082177394185903907, - 10201298324909697255105265958780781450978049256931478989759448189112393506592, - 13564695482314888817576351063608519127702411536552857463682060761575100923924, - 9262808208636973454201420823766139682381973240743541030659775288508921362724, - 173271062536305557219323722062711383294158572562695717740068656098441040230, - 18120430890549410286417591505529104700901943324772175772035648111937818237369, - 20484495168135072493552514219686101965206843697794133766912991150184337935627, - 19155651295705203459475805213866664350848604323501251939850063308319753686505, - 11971299749478202793661982361798418342615500543489781306376058267926437157297, - 18285310723116790056148596536349375622245669010373674803854111592441823052978, - 7069216248902547653615508023941692395371990416048967468982099270925308100727, - 6465151453746412132599596984628739550147379072443683076388208843341824127379, - 16143532858389170960690347742477978826830511669766530042104134302796355145785, - 19362583304414853660976404410208489566967618125972377176980367224623492419647, - 1702213613534733786921602839210290505213503664731919006932367875629005980493, - 10781825404476535814285389902565833897646945212027592373510689209734812292327, - 4212716923652881254737947578600828255798948993302968210248673545442808456151, - 7594017890037021425366623750593200398174488805473151513558919864633711506220, - 18979889247746272055963929241596362599320706910852082477600815822482192194401, - 13602139229813231349386885113156901793661719180900395818909719758150455500533, - ]; +#[foreign(keccak256)] +pub fn keccak256(_input: [u8; N], _message_size: u32) -> [u8; 32] {} - let mut r = 0; - for elem in array { - let h = mimc(elem, r, constants, exponent); - r = r + elem + h; - } - r -} diff --git a/noir_stdlib/src/hash/mimc.nr b/noir_stdlib/src/hash/mimc.nr new file mode 100644 index 00000000000..10c0a48917c --- /dev/null +++ b/noir_stdlib/src/hash/mimc.nr @@ -0,0 +1,125 @@ +// mimc-p/p implementation +// constants are (publicly generated) random numbers, for instance using keccak as a ROM. +// You must use constants generated for the native field +// Rounds number should be ~ log(p)/log(exp) +// For 254 bit primes, exponent 7 and 91 rounds seems to be recommended +fn mimc(x: Field, k: Field, constants: [Field; N], exp: Field) -> Field { + //round 0 + let mut t = x + k; + let mut h = t.pow_32(exp); + //next rounds + for i in 1..constants.len() { + t = h + k + constants[i]; + h = t.pow_32(exp); + } + h + k +} + +global MIMC_BN254_ROUNDS = 91; +//mimc implementation with hardcoded parameters for BN254 curve. +#[field(bn254)] +pub fn mimc_bn254(array: [Field; N]) -> Field { + //mimc parameters + let exponent = 7; + //generated from seed "mimc" using keccak256 + let constants: [Field; MIMC_BN254_ROUNDS] = [ + 0, + 20888961410941983456478427210666206549300505294776164667214940546594746570981, + 15265126113435022738560151911929040668591755459209400716467504685752745317193, + 8334177627492981984476504167502758309043212251641796197711684499645635709656, + 1374324219480165500871639364801692115397519265181803854177629327624133579404, + 11442588683664344394633565859260176446561886575962616332903193988751292992472, + 2558901189096558760448896669327086721003508630712968559048179091037845349145, + 11189978595292752354820141775598510151189959177917284797737745690127318076389, + 3262966573163560839685415914157855077211340576201936620532175028036746741754, + 17029914891543225301403832095880481731551830725367286980611178737703889171730, + 4614037031668406927330683909387957156531244689520944789503628527855167665518, + 19647356996769918391113967168615123299113119185942498194367262335168397100658, + 5040699236106090655289931820723926657076483236860546282406111821875672148900, + 2632385916954580941368956176626336146806721642583847728103570779270161510514, + 17691411851977575435597871505860208507285462834710151833948561098560743654671, + 11482807709115676646560379017491661435505951727793345550942389701970904563183, + 8360838254132998143349158726141014535383109403565779450210746881879715734773, + 12663821244032248511491386323242575231591777785787269938928497649288048289525, + 3067001377342968891237590775929219083706800062321980129409398033259904188058, + 8536471869378957766675292398190944925664113548202769136103887479787957959589, + 19825444354178182240559170937204690272111734703605805530888940813160705385792, + 16703465144013840124940690347975638755097486902749048533167980887413919317592, + 13061236261277650370863439564453267964462486225679643020432589226741411380501, + 10864774797625152707517901967943775867717907803542223029967000416969007792571, + 10035653564014594269791753415727486340557376923045841607746250017541686319774, + 3446968588058668564420958894889124905706353937375068998436129414772610003289, + 4653317306466493184743870159523234588955994456998076243468148492375236846006, + 8486711143589723036499933521576871883500223198263343024003617825616410932026, + 250710584458582618659378487568129931785810765264752039738223488321597070280, + 2104159799604932521291371026105311735948154964200596636974609406977292675173, + 16313562605837709339799839901240652934758303521543693857533755376563489378839, + 6032365105133504724925793806318578936233045029919447519826248813478479197288, + 14025118133847866722315446277964222215118620050302054655768867040006542798474, + 7400123822125662712777833064081316757896757785777291653271747396958201309118, + 1744432620323851751204287974553233986555641872755053103823939564833813704825, + 8316378125659383262515151597439205374263247719876250938893842106722210729522, + 6739722627047123650704294650168547689199576889424317598327664349670094847386, + 21211457866117465531949733809706514799713333930924902519246949506964470524162, + 13718112532745211817410303291774369209520657938741992779396229864894885156527, + 5264534817993325015357427094323255342713527811596856940387954546330728068658, + 18884137497114307927425084003812022333609937761793387700010402412840002189451, + 5148596049900083984813839872929010525572543381981952060869301611018636120248, + 19799686398774806587970184652860783461860993790013219899147141137827718662674, + 19240878651604412704364448729659032944342952609050243268894572835672205984837, + 10546185249390392695582524554167530669949955276893453512788278945742408153192, + 5507959600969845538113649209272736011390582494851145043668969080335346810411, + 18177751737739153338153217698774510185696788019377850245260475034576050820091, + 19603444733183990109492724100282114612026332366576932662794133334264283907557, + 10548274686824425401349248282213580046351514091431715597441736281987273193140, + 1823201861560942974198127384034483127920205835821334101215923769688644479957, + 11867589662193422187545516240823411225342068709600734253659804646934346124945, + 18718569356736340558616379408444812528964066420519677106145092918482774343613, + 10530777752259630125564678480897857853807637120039176813174150229243735996839, + 20486583726592018813337145844457018474256372770211860618687961310422228379031, + 12690713110714036569415168795200156516217175005650145422920562694422306200486, + 17386427286863519095301372413760745749282643730629659997153085139065756667205, + 2216432659854733047132347621569505613620980842043977268828076165669557467682, + 6309765381643925252238633914530877025934201680691496500372265330505506717193, + 20806323192073945401862788605803131761175139076694468214027227878952047793390, + 4037040458505567977365391535756875199663510397600316887746139396052445718861, + 19948974083684238245321361840704327952464170097132407924861169241740046562673, + 845322671528508199439318170916419179535949348988022948153107378280175750024, + 16222384601744433420585982239113457177459602187868460608565289920306145389382, + 10232118865851112229330353999139005145127746617219324244541194256766741433339, + 6699067738555349409504843460654299019000594109597429103342076743347235369120, + 6220784880752427143725783746407285094967584864656399181815603544365010379208, + 6129250029437675212264306655559561251995722990149771051304736001195288083309, + 10773245783118750721454994239248013870822765715268323522295722350908043393604, + 4490242021765793917495398271905043433053432245571325177153467194570741607167, + 19596995117319480189066041930051006586888908165330319666010398892494684778526, + 837850695495734270707668553360118467905109360511302468085569220634750561083, + 11803922811376367215191737026157445294481406304781326649717082177394185903907, + 10201298324909697255105265958780781450978049256931478989759448189112393506592, + 13564695482314888817576351063608519127702411536552857463682060761575100923924, + 9262808208636973454201420823766139682381973240743541030659775288508921362724, + 173271062536305557219323722062711383294158572562695717740068656098441040230, + 18120430890549410286417591505529104700901943324772175772035648111937818237369, + 20484495168135072493552514219686101965206843697794133766912991150184337935627, + 19155651295705203459475805213866664350848604323501251939850063308319753686505, + 11971299749478202793661982361798418342615500543489781306376058267926437157297, + 18285310723116790056148596536349375622245669010373674803854111592441823052978, + 7069216248902547653615508023941692395371990416048967468982099270925308100727, + 6465151453746412132599596984628739550147379072443683076388208843341824127379, + 16143532858389170960690347742477978826830511669766530042104134302796355145785, + 19362583304414853660976404410208489566967618125972377176980367224623492419647, + 1702213613534733786921602839210290505213503664731919006932367875629005980493, + 10781825404476535814285389902565833897646945212027592373510689209734812292327, + 4212716923652881254737947578600828255798948993302968210248673545442808456151, + 7594017890037021425366623750593200398174488805473151513558919864633711506220, + 18979889247746272055963929241596362599320706910852082477600815822482192194401, + 13602139229813231349386885113156901793661719180900395818909719758150455500533 + ]; + + let mut r = 0; + for elem in array { + let h = mimc(elem, r, constants, exponent); + r = r + elem + h; + } + r +} diff --git a/noir_stdlib/src/hash/poseidon.nr b/noir_stdlib/src/hash/poseidon.nr index c0a31f2d0ea..b3cb32cd357 100644 --- a/noir_stdlib/src/hash/poseidon.nr +++ b/noir_stdlib/src/hash/poseidon.nr @@ -1,5 +1,4 @@ mod bn254; // Instantiations of Poseidon for prime field of the same order as BN254 - use crate::field::modulus_num_bits; struct PoseidonConfig { @@ -11,95 +10,76 @@ 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 - assert(t as u8 * (rf + rp) == ark.len() as u8); + let mul = crate::wrapping_mul(t as u8, (rf + rp)); + assert(mul == ark.len() as u8); assert(t * t == mds.len()); assert(alpha != 0); - - PoseidonConfig {t, rf, rp, alpha, ark, mds} -} + PoseidonConfig { t, rf, rp, alpha, ark, mds } +} // General Poseidon permutation on elements of type Field -fn permute( - pos_conf: PoseidonConfig, - mut state: [Field; O]) - -> [Field; O] { +fn permute(pos_conf: PoseidonConfig, mut state: [Field; O]) -> [Field; O] { let PoseidonConfig {t, rf, rp, alpha, ark, mds} = pos_conf; assert(t == state.len()); - - let mut count = 0; + let mut count = 0; // for r in 0..rf + rp - for r in 0..(ark.len()/state.len()) { + for r in 0..(ark.len() / state.len()) { for i in 0..state.len() { state[i] = state[i] + ark[count + i]; } // Shift by round constants - state[0] = state[0].pow_32(alpha); - // Check whether we are in a full round - if (r as u8 < rf/2) | (r as u8 >= rf/2 + rp) { + if (r as u8 < rf / 2) | (r as u8 >= rf / 2 + rp) { for i in 1..state.len() { state[i] = state[i].pow_32(alpha); } } - + state = apply_matrix(mds, state); // Apply MDS matrix count = count + t; } state } - // Absorption. Fully absorbs input message. -fn absorb( +fn absorb( pos_conf: PoseidonConfig, mut state: [Field; O], // Initial state; usually [0; O] rate: Field, // Rate capacity: Field, // Capacity; usually 1 - msg: [Field; P]) // Arbitrary length message - -> [Field; O] { + msg: [Field; P] +) -> [Field; O] { assert(pos_conf.t == rate + capacity); - + let mut i = 0; for k in 0..msg.len() { // Add current block to state state[capacity + i] += msg[k]; i = i+1; - // Enough to absorb if i == rate { state = permute(pos_conf, state); i = 0; } } - // If we have one more block to permute if i != 0 { state = permute(pos_conf, state); } - + state } - - // Check security of sponge instantiation fn check_security(rate: Field, width: Field, security: Field) -> bool { let n = modulus_num_bits(); - ((n-1)*(width-rate)/2) as u8 > security as u8 + ((n - 1) * (width - rate) / 2) as u8 > security as u8 } - // A*x where A is an n x n matrix in row-major order and x an n-vector fn apply_matrix(a: [Field; M], x: [Field; N]) -> [Field; N] { let mut y = x; @@ -107,9 +87,9 @@ fn apply_matrix(a: [Field; M], x: [Field; N]) -> [Field; N] { for i in 0..x.len() { y[i] = 0; for j in 0..x.len() { - y[i] = y[i] + a[x.len()*i + j]* x[j]; + y[i] = y[i] + a[x.len()*i + j]* x[j]; } } - + y } diff --git a/noir_stdlib/src/hash/poseidon/bn254.nr b/noir_stdlib/src/hash/poseidon/bn254.nr index fadf45138ab..0db6d9546dc 100644 --- a/noir_stdlib/src/hash/poseidon/bn254.nr +++ b/noir_stdlib/src/hash/poseidon/bn254.nr @@ -4,13 +4,10 @@ mod consts; use crate::hash::poseidon::PoseidonConfig; use crate::hash::poseidon::apply_matrix; - // Optimised permutation for this particular field; uses hardcoded rf and rp values, // which should agree with those in pos_conf. -pub fn permute( - pos_conf: PoseidonConfig, - mut state: [Field; O]) - -> [Field; O] { +#[field(bn254)] +pub fn permute(pos_conf: PoseidonConfig, mut state: [Field; O]) -> [Field; O] { let PoseidonConfig {t, rf: config_rf, rp: config_rp, alpha, ark, mds} = pos_conf; let rf = 8; let rp = [56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68][state.len() - 2]; @@ -18,232 +15,222 @@ pub fn permute( assert(t == state.len()); assert(rf == config_rf as Field); assert(rp == config_rp as Field); - - let mut count = 0; + let mut count = 0; // First half of full rounds - for _r in 0..rf/2 { + for _r in 0..rf / 2 { for i in 0..state.len() { state[i] = state[i] + ark[count + i]; } // Shift by round constants - for i in 0..state.len() { state[i] = state[i].pow_32(alpha); } - + state = apply_matrix(mds, state); // Apply MDS matrix count = count + t; } - // Partial rounds for _r in 0..rp { for i in 0..state.len() { state[i] = state[i] + ark[count + i]; } // Shift by round constants - state[0] = state[0].pow_32(alpha); - + state = apply_matrix(mds, state); // Apply MDS matrix count = count + t; } - // Second half of full rounds - for _r in 0..rf/2 { + for _r in 0..rf / 2 { for i in 0..state.len() { state[i] = state[i] + ark[count + i]; } // Shift by round constants - for i in 0..state.len() { state[i] = state[i].pow_32(alpha); } - + state = apply_matrix(mds, state); // Apply MDS matrix count = count + t; } - + state } - // Corresponding absorption. -fn absorb( +#[field(bn254)] +fn absorb( pos_conf: PoseidonConfig, mut state: [Field; O], // Initial state; usually [0; O] rate: Field, // Rate capacity: Field, // Capacity; usually 1 msg: [Field; P] // Arbitrary length message ) -> [Field; O] { - assert(pos_conf.t == rate + capacity); - + let mut i = 0; for k in 0..msg.len() { // Add current block to state state[capacity + i] += msg[k]; i = i+1; - // Enough to absorb if i == rate { state = permute(pos_conf, state); i = 0; } } - // If we have one more block to permute if i != 0 { state = permute(pos_conf, state); } - + state } - // Variable-length Poseidon-128 sponge as suggested in second bullet point of §3 of https://eprint.iacr.org/2019/458.pdf +#[field(bn254)] pub fn sponge(msg: [Field; N]) -> Field { - absorb(consts::x5_5_config(), [0;5], 4, 1, msg)[1] + absorb(consts::x5_5_config(), [0; 5], 4, 1, msg)[1] } - // Various instances of the Poseidon hash function // Consistent with Circom's implementation pub fn hash_1(input: [Field; 1]) -> Field { let mut state = [0; 2]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_2(state)[0] } pub fn hash_2(input: [Field; 2]) -> Field { let mut state = [0; 3]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_3(state)[0] } pub fn hash_3(input: [Field; 3]) -> Field { let mut state = [0; 4]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_4(state)[0] } pub fn hash_4(input: [Field; 4]) -> Field { let mut state = [0; 5]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_5(state)[0] } pub fn hash_5(input: [Field; 5]) -> Field { let mut state = [0; 6]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_6(state)[0] } pub fn hash_6(input: [Field; 6]) -> Field { let mut state = [0; 7]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_7(state)[0] } pub fn hash_7(input: [Field; 7]) -> Field { let mut state = [0; 8]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_8(state)[0] } pub fn hash_8(input: [Field; 8]) -> Field { let mut state = [0; 9]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_9(state)[0] } pub fn hash_9(input: [Field; 9]) -> Field { let mut state = [0; 10]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_10(state)[0] } pub fn hash_10(input: [Field; 10]) -> Field { let mut state = [0; 11]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_11(state)[0] } pub fn hash_11(input: [Field; 11]) -> Field { let mut state = [0; 12]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_12(state)[0] } pub fn hash_12(input: [Field; 12]) -> Field { let mut state = [0; 13]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_13(state)[0] } pub fn hash_13(input: [Field; 13]) -> Field { let mut state = [0; 14]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_14(state)[0] } pub fn hash_14(input: [Field; 14]) -> Field { let mut state = [0; 15]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_15(state)[0] } pub fn hash_15(input: [Field; 15]) -> Field { let mut state = [0; 16]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_16(state)[0] } pub fn hash_16(input: [Field; 16]) -> Field { let mut state = [0; 17]; for i in 0..input.len() { - state[i+1] = input[i]; + state[i+1] = input[i]; } - + perm::x5_17(state)[0] } diff --git a/noir_stdlib/src/hash/poseidon/bn254/consts.nr b/noir_stdlib/src/hash/poseidon/bn254/consts.nr index ef4d5a6fce4..62b5f4b5212 100644 --- a/noir_stdlib/src/hash/poseidon/bn254/consts.nr +++ b/noir_stdlib/src/hash/poseidon/bn254/consts.nr @@ -2,21 +2,18 @@ // Consistent with https://github.com/iden3/circomlib/blob/master/circuits/poseidon.circom and https://github.com/iden3/circomlib/blob/master/circuits/poseidon_constants.circom use crate::hash::poseidon::PoseidonConfig; use crate::hash::poseidon::config; - // Number of full rounds global rf = 8; - // Number of partial rounds fn rp() -> [u8; 16] { [56, 57, 56, 60, 60, 63, 64, 63, 60, 66, 60, 65, 70, 60, 64, 68] } - // S-box power fn alpha() -> Field { 5 } - // Poseidon configurations for states of size 2 to 17. +// noir-fmt:ignore pub fn x5_2_config() -> PoseidonConfig<128, 4> { config( 2, @@ -28,6 +25,7 @@ pub fn x5_2_config() -> PoseidonConfig<128, 4> { ) } +// noir-fmt:ignore pub fn x5_3_config() -> PoseidonConfig<195, 9> { config( 3, @@ -38,7 +36,7 @@ pub fn x5_3_config() -> PoseidonConfig<195, 9> { [7511745149465107256748700652201246547602992235352608707588321460060273774987,10370080108974718697676803824769673834027675643658433702224577712625900127200,19705173408229649878903981084052839426532978878058043055305024233888854471533,18732019378264290557468133440468564866454307626475683536618613112504878618481,20870176810702568768751421378473869562658540583882454726129544628203806653987,7266061498423634438633389053804536045105766754026813321943009179476902321146,9131299761947733513298312097611845208338517739621853568979632113419485819303,10595341252162738537912664445405114076324478519622938027420701542910180337937,11597556804922396090267472882856054602429588299176362916247939723151043581408]) } - +// noir-fmt:ignore pub fn x5_4_config() -> PoseidonConfig<256, 16> { config( 4, @@ -49,7 +47,7 @@ pub fn x5_4_config() -> PoseidonConfig<256, 16> { [16023668707004248971294664614290028914393192768609916554276071736843535714477,17849615858846139011678879517964683507928512741474025695659909954675835121177,1013663139540921998616312712475594638459213772728467613870351821911056489570,13211800058103802189838759488224684841774731021206389709687693993627918500545,19204974983793400699898444372535256207646557857575315905278218870961389967884,3722304780857845144568029505892077496425786544014166938942516810831732569870,11920634922168932145084219049241528148129057802067880076377897257847125830511,6085682566123812000257211683010755099394491689511511633947011263229442977967,14672613178263529785795301930884172260797190868602674472542654261498546023746,20850178060552184587113773087797340350525370429749200838012809627359404457643,7082289538076771741936674361200789891432311337766695368327626572220036527624,1787876543469562003404632310460227730887431311758627706450615128255538398187,21407770160218607278833379114951608489910182969042472165261557405353704846967,16058955581309173858487265533260133430557379878452348481750737813742488209262,593311177550138061601452020934455734040559402531605836278498327468203888086,341662423637860635938968460722645910313598807845686354625820505885069260074] ) } - +// noir-fmt:ignore pub fn x5_5_config() -> PoseidonConfig<340, 25> { config( 5, @@ -60,7 +58,7 @@ pub fn x5_5_config() -> PoseidonConfig<340, 25> { [16789463359527776692258765063233607350971630674230623383979223533600140787105,17179611066821656668705197789232102741366879862607190942874777813024566441829,18653277315487164762584377009009109585010878033606596417396490909822722930739,7373070639853668650581790286343199505413793790160702463077019294817051722180,4823864393442908763804841692709014014130031798360007432734996408628916373879,19196309854577132760746782449135315310664418272926255500908899397538686486585,18123132816088485879885148351452823314623055244145916622592591084094232513914,18436594886553181913092702411547018228276047601279727265790147051821171174455,15167500404313194506503404655898040457721633218143681920692711693000769735187,9437986152015460505719924283993842205604222075968464846270136901243896809793,21445376105821232747280055223032050399373725161014449207033808524504027971613,49684738714301073369749035791061182456037935161360748355432247732088942674,9826409059947591908303145327284336313371973037536805760095514429930589897515,8494798325496773219358794086647759478982958403252584257436898618394561204124,21251937175072447337747316555423152807036003235223125066270735279039060889959,5539100337780919206842837176908516952801756637410959104376645017856664270896,6297628909516159190915174165284309160976659474973668336571577778869958189934,12792263637464508665199868777503118105486490400267592501708855807938962470650,17254685306085558791725544672172906900581495686070720065168939143671412445514,3590396502942934679818900672232030233017710909687947858184099000783280809247,19055249881366445073616526879263250763682650596233071589085239500077496415637,7367697936402141224946246030743627391716576575953707640061577218995381577033,1322791522030759131093883057746095061798181102708855007233180025036972924046,20456741074925985565499300081580917471340328842103779922028754640077047587707,9059147312071680695674575245237100802111605600478121517359780850134328696420] ) } - +// noir-fmt:ignore pub fn x5_6_config() -> PoseidonConfig<408, 36> { config( 6, @@ -71,7 +69,7 @@ pub fn x5_6_config() -> PoseidonConfig<408, 36> { [8266021233794274332054729525918686051968756165685671155584565440479247355160,7947823415909040438587565055355894256799314737783432792935458921778371169026,16508811191852041977017821887204137955816331040385276110261643892701458724933,1804800467126006102677564831888710635194614232739335985819349312754063580223,11189892034806587650995829160516587240879881493093022855087765921356611070470,20567450145123179140729389574352706949280207113956641415022972885523439610844,4666756311257455192796774305229624459258864488677689058174087310651786875914,11389253665835451896363091846189307652796786468610595637047377864063404843117,18793736599347263150867965517898541872137378991464725717839931503944801692688,4206344588923325482680116848820594823631536459347642329098796888497153867720,1739462481670645248707834504605096139894257554120906850613041004917967456145,18514227342636266640333254638454588508118462110178719555586534011641424431745,17887039315911403193186866703775654467672391491657957999455462537283842145802,2824959020572825365047639014537190268717891749361604043531643698340708119767,12521547103713919592301476538318318223836047611311454785951907894055964264287,8658146183671258251984364885894342376430874614261222570603159082682815800788,154390145585284450772861151318029820117470958184878116158462181541183085587,7593705166056392393963956710828665339496927193740869686529339432486182720653,5529559239163081088908568555890212324771345012509269613465629182165427812002,3729910453162885538930719732708124491456460687048972152311428493400220125686,11942815243552870715777415109008273807076911177089425348095503288499102855779,498938524453430895689241565973888863905147713935369405079343247530256066618,3976257517234324421403708035200810671331954932478384823208414346189926720724,723540703523219510043977323240437576248315561543814629392162302024056718473,13306548824219676333032339487546407241767961556934015003605485324283250885682,7970147269291664639740298762956131361316495463191268382513594527221399186752,20633313939958767604804835838065337107615699351647541991788258289962727735454,17162090859520817529294904484646695645841022315617926715432606252643123848792,9181379842957190051440498041153333325098774266789773971685141362947015398641,7051606617662816798224904133351061549832959857069896192072217769241273559278,16619522548478824222688310091434959542211899852679631815023615875678448806029,14965311177811968100298579672135357167599499478246106482433786066289128683961,9792733250919070275775594069208673385381167169182805600474820364274865306108,2069253833779081039049908513863485270550301879399727430830923273191877809560,15847298987712771667136245955631872888473964330474501593909263901393348546986,12244443532166430060291409356011430759892629145539185535677568234713942157668] ) } - +// noir-fmt:ignore pub fn x5_7_config() -> PoseidonConfig<497, 49> { config( 7, @@ -82,7 +80,7 @@ pub fn x5_7_config() -> PoseidonConfig<497, 49> { [19332164824128329382868318451458022991369413618825711961282217322674570624669,12346323761995603285640868741615937712088302657627126374070962894016296466118,3913895681115272361294397190916803190924061797587910478563401817340941991811,7048322889096718105055545382948709082135086733564574465991576956878202831861,10375086910057323893637057154182902576957472442368661576421122036461645295833,12765622911241487148932810040772504127756393086809438933166282251044289864727,266900212758702307861826326591090138389415348463003233900705815890364224151,14435131616556129905356866638030823183270286404767286105643513738132789033353,5780976801287540146775934937953368730928109502001687434229528186520268917700,1618320442446662026869390273942730786145909339107736579759397243640902802126,3818399583522206096165108192531271582827953520684743806492664825009577810261,11764506724346386316602508039052965575734225646587104133777798242528580374987,2414215974836165993714858157462355581258152126063378817495129367240311967136,17609437036230923129211608175600293197801044251801590649435913902851695334081,363438080029711424794236047863047716381155074181485245036621530063262917196,535766679023716739184211613469394818313893958493710642899297971974381051070,5305068908469731303772738758164870877638068032868328180355958394150421214337,10807632568240507366657354568432178961148417327580695024415275247652313539292,15964415873358391713354948903242729080763777490509563223190335273158191600135,20700362719972015883260687302741075186857660623182772413609788566925949033885,10135127975676256977820296631533839366076919827597067890970660746228807376456,4251490167543116819728642817282216847143714366441358372252125244838181656331,7745587495915033527847242564710473705100826890903278244320948416581724663023,11741113129223221800185946819924457344647035336264986754437921049066977440806,11630296782890656599545188109639399768829653360050213193782325240600583381364,16861140446185941149398487176581839232380972247302922484807333229513905651035,365879246117123675211400356410703684399715291171114630107795112994207447819,21725607857580053522363567649763546934441685061337033780528788383243719579033,9222866548596464928765000608129177609426964853736257576074550520759533736918,10261578281201197531384003420612639018011405529775212563256392340336951230146,15644037447921591571869862919382888810859308861783088910843592577202362807673,12752004188139535619565478547449108772137477456363099481095747591698702436636,4205805109630387448825516813913983509046636797101589615147198457314360427718,21047095155106717901091873146599497621258071512562421967648909471775919992713,15624165295872926124160584750951090817255240214488120310950503163805737026315,15064589937731741958666763896598138037875460434244947486199623542160035749721,1801577872277160959016940766173040841160105238799805406938450020949902989173,2896766420608048344829901127120623317655260981420052771341833288256800199953,12828791469509204618898135640019714232831708508424682785876476343251730674999,21363471986981372923191391880511344708743312828234098289107697080824665183315,21372706354350795416381912271616633829725494570576895047490974943034914894898,16006531510217730955981102005088687858079561573088629102219485906666961331083,2389357602244845938251345005183369360523566673990464798041306722747500447645,15275955107196234672088664710679934029171843237458844492987233368659104714648,8038797517535218686870517662905230585331773059774130312418943649247287196930,17923922393436914864421862212181654800719733137689602673604754147078808030201,12890519745320143484176500044628647247549456778462652469313611980363507314914,8058516556024397257577081553178859094042894928866720408652077334516681924252,768425396034382182896247252731538808045254601036758108993106260984310129743] ) } - +// noir-fmt:ignore pub fn x5_8_config() -> PoseidonConfig<576, 64> { config( 8, @@ -93,7 +91,7 @@ pub fn x5_8_config() -> PoseidonConfig<576, 64> { [12051363189633051999486642007657476767332174247874678146882148540363198906151,6387692555402871022209406699166470377527846400909826148301704257996818597444,5501161701967897191598344153113501150221327945211106479845703139297020305204,11704372055359680530622226011526065512090721245437046184430227296826364812961,1448611482943320179763394986273491989368427112997509352702795612841455555221,11429145481524962708631235759094055797723504985787912972575745356597208940857,18021858528471759023192195347788820214752298716891162685115069036283008604659,19817577944622399780828745167469547332167999743980557486183403063955748437619,16868980302925985719076889965831700407328155411673408077166038059874616424216,14717432944340806781505761211058502775325970511884444497202848327581753493322,6273484270523289845253546319956998489830555038697388950038256377785540828355,7726043103954429233325852791166106732104332590864071922310309250010129731951,21052353119157611359715869265647287129868507410601603360127523286602350622783,14881796557136180514390287939887071460258251160875710427576954128871507002642,16341327439981153879863707938117355436152690262312411284193970279829974799334,10737675906107372302108775622264379258926415910493665638388971468924879578019,17652699767629314433191915267767147860052614073432922215674211498672835339113,7457854400138129895665591719907473144796504905294990100367501377050420942800,2136850802972823585140870808569264373787409642804109426616292140046700710743,14029467347298896610468190615212519453678316548442709087191045978401072380889,17927699952921266007590534383984238136710494507499176330493504416180410161683,1404719213830610030709583332543456268094679432456284386108188509031502237811,15774757292079018355173698870903422490868220545526384876021336136892926326596,13992040374687149195439840459922227749294794072303579532004750946306028893274,19895094843870397064274579657905921299619388074084417486420154568847155746891,943833985612967248618844364501030453998731991825395875139617731659343743483,18334641092245356682448009823797080853859186519922476229272838591594967878678,12440287044655505483131716236615633401781045711053210640202766768864619378050,19130942564098572936370308509908873069169152245172660555660369853346605570826,13687979327148217614616687417475244897906227789285703940171633508277844471062,16887921327479880141959363366262254722342925451159884082370074726344024008329,20378003125024698406589040864014894045124234695859352480989552885205935609512,9961553412530901953022991497331082655746860319830309417179972582392489275965,17755268665220780466271147660314410613992814315871705414495724015443459797439,15394131279964876131165951719955566821453162041574233072088124095626652523043,12668230348320365182085867728169435383987570924921845106243310905832768752125,14046812111383844816383347755263287603387502282980410255379630204396960343368,11590093969266595252327261214735156204516524792938909229175092594303424141199,4623517074925959322927421514289132524032863498392441375476410779446526502799,11550389531965919926150256242174358326491059727918559332939872696684299343135,408487396317981846281976563618407581852133413686169882346565860317912856432,10717757571561029382519744040791773994731123262749372629687813122941078154016,21323787615496251932181222397986048515693661833099659753170924658480548866921,20780799310067873093555276926357624414275975377319941015818682052081980020892,9948385944800296129032348634683354181546876394979291412116493575442898426065,4957033413111065858035065225611730571499258914257595411830870977545212164095,5227254936689728148737265263965107718869714128941995977191096572191110991079,3582814872786080867997255427740166393615552773099677831398251586195329933975,2136737803483410555580163900871515004623198990079556379647848364282254542316,2965752098571712086281180512370022839542603960309127077035724860894697782076,1478525086510042909660572998242949118476342047444968703549274608283885678547,3563375996604290844805064443647611841824012587505923250907062088840679700555,15461452581843517997080348781604020486994675070532901120353124746087231692278,20472517020063295821544268171575414161230806406668271887185150097779785573889,21058001005918321995459971112208002381460494177332965873048074199074929946172,15805746645980285645504697043988763170971539673993759868487715403982423015009,7141240965656437676130015766799708612940092856280620325870466265817008351948,21418010338098024788434337801477243267248314524079104488811186206038748626642,20272108634229595317682817969506273496034097230124371921628691470754475805838,16734095147399743907618148751687506877774623133599770145304816136018239803101,8439324632051181834455499457268557602816180314723268640869118054114888151316,4953900961796661020464968131122569974581908893169105485631905994366550928492,18071625983692455679240094911529791119099077429122520426399552756115503123111,19638917592063029281156873227053827678889868373299664608974791764751784473040] ) } - +// noir-fmt:ignore pub fn x5_9_config() -> PoseidonConfig<639, 81> { config( 9, @@ -104,7 +102,7 @@ pub fn x5_9_config() -> PoseidonConfig<639, 81> { [708458300293891745856425423607721463509413916954480913172999113933455141974,14271228280974236486906321420750465147409060481575418066139408902283524749997,15852878306984329426654933335929774834335684656381336212668681628835945610740,14650063533814858868677752931082459040894187001723054833238582599403791885108,5582010871038992135003913294240928881356211983701117708338786934614118892655,17817167707934144056061336113828482446323869140602919022203233163412357573520,16618894908063983272770489218670262360190849213687934219652137459014587794085,10883405878649359800090160909097238327402403049670067541357916315880123123342,7439184039942350631846254109167666628442833987137988596039526179738154790587,2727663760525187222746025175304386977552466570311228286110141668880678011929,16992375884417886634716738306539629570444547136030480542879886913528563834233,4178586893949624406750122665277033849762243490544460031634329370298105635905,2517914797385699886738929430037355069462619900197972886482360691236776726214,20164173810534657634631187494276970100735049909727379228976555863615716408280,19970958827248077001061220127605534603528515080207197493660642269195127427214,15606275977308968307194602612931727810866183872589808138812916593200446820753,12261436001550634140750381230737452634746867040398895669545077774504957433511,10405309809257831434323731445544896504541938387524726028487604098725193737428,13408856444092113657034337770571899796129642125690066226794939383190876435468,19768080898957882918527124226120459667739640387901357739011662191034806046251,16749889646056241484852997428132695501278739424507088920371060969471495213919,12331609790192161246735870679870317366088443875784324655482358218146673901073,15769331739277556832196167201116801527901089923090632364403958141614820528626,5227172275505968397128736045169568430462701766148126842874241545343535393924,919073378344729780131814412541912290691661039815032069498359347682919854836,17858725475505870077023114050620337312678855554361132257763133392017321111169,21805188450184460363143840112266872832328782034569970452376470141743078343745,15808413311863154368918155104905222670782553225279887458053980771135357021692,12828907214414139667587331812274388831051429093098655261887619166452245292431,19323880880917307340820066456419195877039970908109908221992925424585030574269,17591732412986269470826282099678922890996647592922237928486497997144096433314,5282593184575641056912422403901924986019740793240905758215569065763629999318,16013130707598525718519250412251656096494468043256226360413191733653074896117,928381583587170989315021718439506896903185927814675820160976165627097308915,13354336789663524324458402003354905134416094005220899335023797754517805691310,8780135673134081873589118311874067764073719549433574820315100541871522642766,3334957744389892864165113989538814646945861179021194859030934481494560681812,10553413566358881045095498839713459314577909144176577153981801574128014927353,18894321506279909207228932263261226433242541255661384643559047811974513999438,20211894014628303327332299342564779073614790317614402383971270594430055013904,16723480621932556506775906903415088312771104391224076734252099577243237899106,1131872547334579236404174618548801749854242069301712398106619948805304881636,17386814048141719093058723520379257085987299288710382497237609774141718421404,13729980537487612221640320393867198844745491357830417754869369043292518007370,15860780436383591737179656321807464721751913977397035980422407138400867838633,14708550460111247278740231297332510059116901767161326454481923990389610737973,3132820559166321299152015048428879769905404947939291493327190426785911502819,8658132367999084824971296219169212568783540935524918908332001856872807119287,21064783047501777742084787259676320053480170916619513986794406566953069418035,20731000104011695148048713576219525164619502119638555785381543866326561323,17189725817866212967650950297463469529475851286172280116066228706121595462088,3310440878606659516028312898499559492876015493892608849966645073367377278233,18463918215326370595980949760897480127622730018343709491036454088497976892863,10894192430593140913557164014343360386192963621862346779515699758352916852228,5060610877870389107953459328006060153180283860738879092399406248484265273634,9068988823145592214189961315730261367007076042069390630024839612151270430414,13160707893890865447331361630522644819624543031829773191665491273833460019183,13920568292534026180186486064598876780779571940988254327823480971820885713801,3894011501178134026216736522445829906312115650019712122802932677318433032635,17895318821130376385979570244603067634449453259842805202694945793852667231847,9777993060458301797155055013115849176281006051494461044565335406558308324220,16521293541516305251718414192107787058980727971856888501176820100904791554730,7744063601405355255689420547832904761861257642931934580021876189691881462544,5444730929053688962452159157646022068806222098484627080046464163159451208522,1524118152994294864739915388438939180298324297960159419600850033701763764640,1334622237342346242862023763160346671504959163544406543315614662442562816653,16126317914306849967682996412350336172782726693375105190424151365140854833923,6345975085253358297751050638846919833013142450462810543971050115910612860460,2703875280053263252177031410407166981522153304496807669518295313468095058674,20550626512184448884716175825490086259235894802178999642552696391947509065676,15013718986700828670892638677446258841869291160144196138236407826511808592486,4682264015512203762723381542642871160915706748420642731100634327658667608042,12834108073603507925748862283503586970613250684810871463629807392488566121352,8422606792378744850363509404165092879785007388646473871019846954536829739979,9339209090550177650528715604504958143078492516052997365409534971861874881780,9141831918422847136631159987994781722269889810731887947045878986971886716767,18329180549061748373684938917948729366786279119056979983310618862430068636631,2009551904565170718789964252583363785971078331314490170341991643087565227885,3859729780601667888281187160881197567257456581829833310753128034179061564519,8535335342372994336873304745903510543599314397287086554558824692658347277251,14148514289641991520153975838000398174635263164584825009402034843810351225518] ) } - +// noir-fmt:ignore pub fn x5_10_config() -> PoseidonConfig<680, 100> { config( 10, @@ -115,7 +113,7 @@ pub fn x5_10_config() -> PoseidonConfig<680, 100> { [5029285279710800539227619495938136407778783814400587102957398897867261120664,21661833903534656620291231766157513264428291380933208423519374035927473262119,21013170147855726227668315492699186959893088673047129690411646575996043835024,15893628062504267735591398483514002406192781085288489283447316241330749546879,9860639032243003377544947110034203265885715041305770375052648470285182020229,10431760628292478929366440566994655480900443273305000842144090945543100651218,4662341343242273661833461144031815716144681076466659112993661636426666579986,6674279191498784183427663914511569570797862586816649467168170855788360268943,16895097041920841073767278653214275321407577186751547609698446652984399225877,8168606076413192332279322347673356872630772122089948509553934257426773045038,12091567755121016869657080116466607855522522017768906776539212195551888602502,4684576201081771194613696765517034834984066296253124029929753160055156611363,16693488266039456124835102259365515976900969074532557489095946797080826193662,7638443036775258881709317582832080783911189229963788890221615286494482929025,10111436214822932149781668218956845833675824936886829015449750181332010388640,896682691957564465177669890535917423987915406885797833670239687119295318467,12612639059115228106858238115822505521432423470330120640591982767272085175034,1851711744209473345586117150836616408053748535684022739058625441026889320297,14132260688735080257390420980422269734275443926576061985351678038992087770902,487493866037948515547037886552479973316400139387425953088274857424154262588,7712516772901240105339429973116360243232161870164307482409826131312962380842,20295556720945067049585659016570679551265845058805648954004989969704769135170,378208946912325140295069471345064814132951473534378635003955801655986417900,15111601008893945567629460471315838423301021468457758533702272669431620017222,1503682435556321218669089857094247703956565058167121192612334331910088441071,13084874799693933186811120569396911285611047490876409383659779579088985591229,17464483161247836988344436558341194021876261750085348252730901647076441211862,6628743087463083391707355927377412170189936607932592258517748766250528223430,15153763588458144568353947674975114179172744555450771328418442212716084083525,11217853102739260248713425002157925483291370125178251466195670948291389406199,11275485266433075885440484136400353724892671196084163231314370685019444807048,20167106354875398113371399754994549089359568833089630824992752829251678891797,14151330869211746069130604993916224881047448810615413435448712767752320095045,17260356243574396880210370581740651566334589568095587416844511054569255137183,12436078462666286197074526218535647721230687376129721353230123441759960021666,12001627458343654011606323250787666795709808266974343548842843520227918922255,15944850302839498288636342399223012131590208876255723227505947857641523034493,8444103924869263585176528654612076203716402818569041992813095331662367021655,13015682914180762871967848617514355587762125694235380084430680565032083402270,16200183380426364054409550129683752323493215428097334915015688753327665325485,13717643109958965551675619584464549580820722892266661529182798599670194908199,19801725181447377274232761944437523251067599053402428862557912155522673980500,8260354277364856843022982286494019620277496829494935775254726797533957063267,124621144162335766862972192337737579448571172779117809776129849377329817478,16488884047551411705397223604196364132975353217876182634038895586664127388979,17336432076451490238716890901095007360946878388179175784603587179384718443321,1210338460555723584699132156502555539583432069430631008706741082485009017102,5933432012048351362807861976737945204535374770355507745694008880123055490802,5127952499969178010015035020598142881788437616516517827214405489972695632240,21100924218139544842807404598627913291698574448527131003096325470925085906016,7683521602764604419863026286445694988900727173175219514555132623764360793654,20928394065137007852706990901925870323120588543710137320004640014111073449000,21375535333469484792161302750563386607223088895810564711097025913956371171769,8663517227154706072248636076587789834246541965140682871530851124960776424787,9182938389356039217318590654716613493414550996824701664670650439783557720226,8327338979442122743919832154397496089418582414082199116629974300650113777515,2474727241701323049333019668054716886184808783449917153147248751503852312804,8543922237501430855864877057711792269479294116675004771113148647309219620030,7863611214303285947093025404346084345102544167615769255495752297507346719791,1448902069752048144992778676670381235906144579949631101518897035253311063307,19501657783346989621892787238946890715709847672294934508902622542828235185048,17076525025777667838921778388186176564387475624769926249793144074465528465933,2381176586418291387279201678056498732033435079507661703992537801751492053086,20723508866659831749949206314442193102431573526415976696387848305764994281574,17461795780729443663350296040956479984433953861306521086706732257263430387445,14849025218838139413138931958408289986915143240245452275066866730847749323920,21207204042106390965753782189145584243052148578812105334769740484186308017901,3105302592226642624386332562899903659948819667537402316192380465808886843623,8765266846991616382097124552983206033439769882065573909634090515268812396114,9950016446092650730639179912416912603745831292536616469358668786853463197224,11739731747351277092817771330729393674312591071236310446088293450266807414263,5424991773995591044103668717299468589013142114099340604018933512575789323446,14582885509715812510585748465607279869582209618804039923778041514988867577359,12468934763690970929325823037406509081405444759649987929912706732364016057892,2792793293657306144108993077959195845478902430027171873963281969527327256602,8841327809851437433386666692145437950603022633472031964220924157605803799391,7845859360796082275932181771457755704129556353505380746504571839006944723429,10731793207832149137187382442869034250153492853628224932026933458041993639295,5597792614864287090861003890414825257635680048696075527563498604714157576447,2638669099010916296300870639816763122907432841565512299246441500223692345671,7150832464835357604208338666096132398994318721877322228060899549998179405057,5470477812928960639347760417261508685840724903499112719517942324191018679706,1063854480993555660259858748055514950231824974684462401269695511649059715242,14508243449586598349750829047481358081191713699373322296041764577478835760927,14872220983064543437506211589956319796231014912750035729896461676577407407598,9523202653584689553554068772241228948237208444616905879849472383190180438058,10557133197819890801524243760013157188954914093770589635201319240903423455316,4973822148190287060777561091733583032026446820262414806412485028147721872972,12017319043066808147670914562193696608548297038020764496633388575589573229927,20958507279974171556413354796214800332148109902768069171659933168603089927180,16142225389165963605704721785850680620029805525816101628767304750729950332962,21691255103889531967215183091383836488808797368461467004501598817850515277674,13360009791215314413428942977255018953699328534302248245107197249816193370823,5270206696221786165451075835596925139630328202641350960582852969440862939023,2626561181956261201864606929566987806068271006198808163435823619705436605447,5520368836328496672510351296660387187466158872913871354651108826881774455909,21597143280250120305740582323272730661347349587666707484376745221123282421748,5891209530846741397700015863630938364586207627850850447237189083999656313978,1202436381171550812585103405636986166232789491390007497511342220946215395818,9920320882147650877649039705433660083926352954797066179512349368247190410310] ) } - +// noir-fmt:ignore pub fn x5_11_config() -> PoseidonConfig<814, 121> { config( 11, @@ -126,7 +124,7 @@ pub fn x5_11_config() -> PoseidonConfig<814, 121> { [1098498142837982582047608372723518751721607512716925277273595859756333857326,498382712248562027578374863343601618793781182132084383060312181008958381971,19040726265283429618662679510157690394832296024968480927415996691029230011306,10367579130776133414495805974535693744211249758950881275217429221792836643614,1229596364469449066712193908302977020022727834238778132871229393863406546866,5594347757215876411130934611555467571639435097442631641074898978663329410864,625275312666547608222628560378372315159605662141936411119837279426221363981,15485529557721639677666143827295121022852505628489596851713462276650737776670,12156576509577081554587930818670905775536581975823788207855134544267814269606,1981640929928975005466842670997136169304057407742291166386016130552621471939,9375079124430521740651903984797221620963928972304905809259607327125669559872,268697279437287801043057266739136500465135819021738115532631740070584831216,9310725094036396036773344350803037792624399505581573214229419814378683970851,6144934044671205976376028664002834283864020049596457260475210339996948797436,4985941506647510031967748765284991041503308370910665002557248958100799063851,15851062719909725150709309168582658649310704358483047683106225599004779349418,9869770840966008659377598457679699092337106962689936558150689057592239644963,4964286354328869036674130011248598806906438908586967212984901377099285878228,13408525694456518383125684465410538061086669117275911801498275369395798296201,18263306792332242197764383101132914152275840410710698264525919817458731671889,10401786441956087930118823951510684636068781082958380915651220354850381871543,12496745101887166473879957440401384727148915595227764657145046356182346897947,56825204182651219072479187681186238157981743937496557304633023935549648224,7949519580094467639897040111470236633243836928348452962417270559805860514707,3509286722306670968352119363633866055096352721394520084890481975258162907251,21359945526252146173553061920944871506626324563977081669248710516265311530589,14649491209868365229844087258057697734286269047837985905275053819765825128984,12122186136173879572357400046587658543826161883897136171993927935307093999926,2666476328185593105035429309804341325262753927547102747066987631391232293139,21005241858197204874543384881533661499138265185107903730534607574687765896488,4866331653274711303641000079325074227730641553230218424779550288347820225149,938689939079340009195180604139206414955240264736983491692686499992823741696,950493909161345219342597929783079468041198261349024441783356363638640688155,8227093387774305505218050843028014038423742476679149203160700406235271548925,298899716277443866412562171123535849674476895336539413683307522836440058745,6985094123716229565713211140430519589886023406928617334981414752732877292051,4561102873171162160916461632027561255705058072826965137552144392802414262261,15422356128912397775473168682864290042256748428952418907369066530964035265216,21534011877473706794700774934355764894917955655606512952257743854629820348396,9461908500272520643111839486963426035162115487175673718316249722520977894185,9042969964854694648113546554619141983055960736166619708191725199599555275062,1441104948831954255692318866730011748129225465895791664253095290347818907280,19417400621113450826458192671383621002793369580946623762558060167661227354799,8244773274459817591888745631242804467035454174608673362960589130536385507190,17088086767144106377842029064730946925009348520592888187451688601493882340857,12886019902209719236096958359125451092745638766392722988311451127550961945660,20280862819329644063010032903732505647194710429034928708829957501178343790858,13239701144341900586601825324587185682073736334523805955933121583949546821724,2994618864933374534869864629648211464657674590007913715843569952783382900518,3072221011986428615228338853345294533299624086589539664037325300531050793357,13594276105600327401961157952766116939399999497643063180657161489419638074478,12904364780884039213184464580277965622079185353283126471569179129906875486852,15088962493677593800057541234990587773412340265413268221386103386021880406010,14138285403526705785804535000245522290348086552790608567368815987904186155718,13481415964846572771441311017814910258609608797603836070350286657768815710822,15459769479990273742477151452466966963353767555965255520456901549474045452607,8586052864861352028352866296665876117392195296860481710367953704812400661703,180502622991267551120688532508657597773982647209049478186474242637299204110,4785745751361586866577727263713743688205421961646731269452058881240942369409,4583871856798894230250707953295146343968130822948818555994825096960225600041,12377924729639905725281972784629126900954187435957722012223715002490809152047,21554415644278070156493674075483844873249829791940344144484983897474364915950,8390225843490125870104241611355504124284851919520955291024552578484662824128,2330476067094130593913781764168287559468546989640021387799865123741354870445,15749497374252464770935521609391859230015300749964554524771184068776070217841,16817654103281917947623051388088441309787140809596505043937473012669498321704,9987656178378986905964646161927549614205785047077068310684205046327286932204,21450061958292240283686535241652971764195183478875921481624114699420928365160,3904617432242099936494425054740854886663050476318725032541401300619628714123,21454964104289781104446533610149551385791852085041524046710270949744081353102,10768409462143965702783360646769759623397882338491564999208626639994081655791,19385613828688830964519526099114207553837496617978489639408163709100497624509,9385292780799468553063371906778802189174789542685475364513544798199315486080,19882577122462819381545089778080532575686772634821281258975533828284349988146,1462201549484596350490921057903425036211202388283463006651220816599917679116,16564642856725628254155356607086672564976261497486137590399143770170930986182,11606470848655267736219046910932382494518380844147406842964119623341701511194,546921055225672463086391798419385468083264065960104350335293012629066408625,12676737821548820987278730174038033161886561534502963159950183188070064038340,16429180804851559661054910451008618941371882312211198495282444364589225325606,8318514508896823373027050528521007144041407638548138855564062559664141902892,18546910687432012966956995548470714600618104024117576926439677823609854961263,12006683905722730408249989907056432037202625403043550391187503858618155798348,10816814135685807143320832554644398181525372167669730953193258726693903362148,1969445073620598650457101028079888612893685228913473332116076918643068711808,16873795316557869761040796336264749169213884122126281483001377666183529927793,8441268321647668856014389726368355391497206989491787976537908376817970369132,3378086906271763133245748026584767009750550242946195995254881868035794898559,12721353531573613369892164015903035636498816100971168742462654106875931342664,14969430369156214890953989610124286618925370029259450629468188666450865580556,8545723361883060050915916338313252821252873299513393695440138873537985282439,947668284380905375962163908708231363459059635485281084900173592739603282382,4418352807772484492818068921024797225893951828921880350002134747344565378254,18146914067008843660990756743559427698617136456156926109157771781314720068545,2353279078725994188579023195684884389261433430819033940093641668202046052763,18228226015329570627220992288018909552101992748538110505558715089403194764144,2251557590571495628913478692960173580728135227602564510397207128937882297417,20421664597091787362209209474226188711714308866665750343509458297343168321800,8187951594294388715811532560312339537604737243977265499957088579012554679278,15810834190411667509425096842396102750984990364193499272150958331088983323159,16884308240478579935994044823717491481297317573500280152191710196639752382061,234497484353824748419812158321111328486478789224631887096763967543932891899,21452418791072076854500976656696245147472896609273403517249960331326136475572,10860322289080285812992522532751459911253736747190334349942615321085283282595,149826608572716492570322179195234088797160854886751475825283168005807771516,11491761442863092383423796629001188933840969144934642247702733820824608517603,12099180244453415217270377899736157198045626379801787493348249001794558732373,13177983303979037999809722097100345612970493007300007493855625634642663397908,6849052800275826145043024580348093078809773712986428314364827674907764829568,21486255029472594818259653174918852363002807142725698741685253190938680807594,11451503340703054732459437884000132607423536025797075877436151438425159994269,8462539135531767509735697608276067216182907546891182278996691315801807234639,19944711893825824667372913293784300313762563232409638194240029859435259601775,10396631238556297232793544122243237485091433966091043100758266678889110827200,20667999270580360504376758654763163152764187226267414436968564661080084475852,10424436665500877000658892169756884171624649701456443210945810183301667922053,13894422482417998868290238401966517700776990643618129177567797594771207188055,9076475964444407787992938909179730031379198268423789105813333967195259669658,20479003631920854685589262232015009286810147171298477411667705150903826855301,9928015403359312830073752955992978705151208358029077246413002475277600546387,13981618256931763962905358530247354996931923386029793318275706908114940457317] ) } - +// noir-fmt:ignore pub fn x5_12_config() -> PoseidonConfig<816, 144> { config( 12, @@ -137,7 +135,7 @@ pub fn x5_12_config() -> PoseidonConfig<816, 144> { [20214838738486568883466588390719332066160511773018226407137866846447805607366,7161524737853996242838650618412058002168848579199128467811556550737619970970,2264369418377007316930430297757084139629356094085160360541578125176213258694,18691044064909968568998201940845291098399339626807500263611343942450116503516,15978743992268694554518277110515494413411623432213713029162001242329212269562,6711615239704822975151699228936015251056551262955961924747531220602950448829,14954997163751606686696628499315041796272082739441018134122451910369305642115,21573550100361192110069886620445669562472881453105471211193858578537227040439,21785281999660091964290541777959906196912107196794342243439922177000502203701,2946923208312508080510106804563669422427642075683605437758174474435322095802,14039283821812338763616072949057938719426671560747126284782727998420210694521,2531474643515410792989587528850930504447014242967363822821359471367799986101,14281461695965914110119049602449207565231627068856382054789426564141005041994,2155595480001027852247471998853878746887483662385654030663226564169133356539,6212474220474204735846033034823136351584003532895558668927059407038678087162,21589299957493491709069669042662513245508573637668760884022386808061869005942,5228547858762057503048110033821407961973668275986265942002757629551762149969,1151995769496843179907951142523838829938796346663877830241077357918848539138,16195901973518083237059346288792924649902586274815274684503783828189220931050,6205461827971201267719191643863468322713562983419848159871959495317073732623,21004710389082547785746156915318076260017385298749146368429985483091499557183,10094301525352802553607719810440185681054064961117719137647202357989110756759,1174362264673060234121108394303385502501621739298129145129042091221378391858,14586772089804608057953886654898255839796797046217599185042293580394420546552,704103301411330239947625288325002010320119746677418877341164806595452864925,7447867166827402056774077383104558156866119014007569966692643297177923018546,4252152864489296917539284690826221964698345550054947572793948075436067436040,3675525234832046985215853449128143168168428943627479235047788418993254287405,20125795627598431311475910664717716586147044241536953058242999762934679572886,9159576094573932436478222856304524043339640337232471953289062354187369243885,10410289328536677868407694844650868516861553712016012272941004725559785872650,18813119519933909103102649065156934680537361290190751928265976568411443987994,15043786404237278119878717250753259786450872051876817420168142382486008024593,16614805203312302723146840789675006378900903626996105116400354962001922700157,899949298359737140980259063526066233582477211127560605822280959405167872532,8350589775626940122507262589996655703528509795097550101006133878991750882468,10881253968160794744779175936360108103824976232977458894007732866457848744711,19359742822671794584060954988237182553116341604406926658049749172292672638977,10716853194721085390661796797973316855886234718612858006131046035921078793777,1194676839570189281149587289656564753779383829131008000754135056646064455278,11530412134598354110310733773537950950490005376234226554463355736782774653810,7158806839647137330333220334046918613209783693378018773439140974716028082046,18873459493111992992450800068055835432261777460679870727272006783676545919785,4597339034364379110034269874329162788488647975988086437272199171979371177111,16047595573111403874356093398802733070084530893238592035018321960924442437232,192949463851654477795020911703008125546432931266166268873310745978202434603,4826544617576366487123936439697751633333779280970103286526767080486441353413,10372441609969764399977561535165700928227575842447057367716683958896898456242,21479608666927871465054861416648367371602717876964759897062141685818604541372,18757812710789932354215078701254559681588101606101822541277700443926569010598,8502339138598356500092304059172334649791727023646195989902300809704249803746,21240184871409684692673423121366677112492469214890212851758021155034260698420,2702659403779176675766431784851669876796725738129029887042678538644093630255,18760062461290937265331504644060340132840729161526164449611377215801441916965,9598514148929007169331478849372274288455651725546984183500169574552892743616,12460679873938368098608659480431260988399308425323633114529665233186673892475,20582262751655750693560201069767758489467289978119794831247596435694971251287,7495462389257720258504478831214292184152544822380786356126692935003910627822,15847020891468169726540675640439992039404102490965287792626266482436024810091,13444178956365729587956577087448840645730541657243126743158358416431709484781,975733333906184480394673719901416555779305044861384485566696694336272649841,3016935868211088289963870855929013645268121688015888423636516996750583017171,20123197829824640950428347870445510232078708523077317828689832072338303017047,18496031799198869774970797646230665906722932354114482887753612521775690376535,448875332457320150287933426080386825611557032389972932765197125881964153702,15686083476904717209874986881961195356503069952883501862704199048297926079733,7399632407841430295111381086121470926608686430000074868388902950170939693998,19157441199146430337309347165554892283908758853741856357912555742738097866135,16120175937370916934366957179931217076202557540631878137626313655342796978134,17363463873417672052573440102339969267068334412527908172228668014397269133762,19764937897808275673467150361977575240242645746672288031015882089680753193420,4264866715026149043371443488601547814355809386242957666273811883512215893986,15361071774597522987390988933793735468585435977940286138223232105339041682390,13444894080484049025660420839638753203298145906295848687612728375851966859563,21344396291142953621865942956005813155481114773979414786364869990164493168988,13658955537084761077271566555621122724333408573482369456630860179831273897019,12249794154563702076745009616085271813195258124596555920372455161542247237218,2325936171131642979629131064685171177284405924159468319138840745089808621723,3077792516542862676300186898187316876000625806438082696997401720196346610884,21531439209065692564653170259849715075994439889756241721092517464459744953429,765723669836774164873260120197059605145439283015732643840276151768662398969,18430565163341347334129211602477703661982280889871625277638214021594755964149,15168574820004856312411802521805000105968244665018577358614174215627811033660,15609931056593305381714243964783225295053513474263648739398875586829969929857,13057901697952283349663465856361305032896972742145291496691475939407531431061,12802339382735521870414423620343194986509343830854539673006232369799979885569,7880620299082787885902391014823825400306816285911629201048471522567587002433,11085221899164994413080236199596538381402309021910771788195135649489784323294,5662061777175931509849062158785593075054461300898808576328927259801174692172,19620207415640534190314969542389551464821476135583607027506853686406083753807,1396012663571482634431038119696061726217340333644346862093678929991918911771,2833239640477482582925766504780450890721725782645633022528100604619065406714,9289278993548596713194730547769009982667061443580050906003394115646319823584,255970566924787837673441110425992267446525707891905710167559324774004600788,1607914894461957709182037732125046273691353312066921168498378132410220447224,18182823650001333075321511247233769219797858542696762318647781137777390858484,7933393968545943401801081658073805133658457161128306876557740191220424567009,20347911076420909832061080138703827506796370399337016973599032573292195453934,21705355682416154516146726727072637540254191883301906287097797468012136754530,4393707213821090202627671673506613966066953344462172841905371093203947245835,20015218870609611793683104277034599032802947064261475029925414549380954228847,1857954279082383201486002148223947538500417662449637107611316684336169564836,17075622394357639776259605879156105089449277115338468776425087829255085998708,7849339039625631210191134106813689727565217371730065596482503614929894173038,21512601485458872387622978217203423557092449252654722032828165846830386134980,18829825907628826679915224363735067358668372607988097049308159580108100510295,20145344934445170391525281095510437469996020214770888614087514859850402376676,9313354461544201805378332544085825218707302313348145137439630918018863309279,10073510764514576042491642785075889098754556687860419668420630560526859371108,11174613823246619246542059297257164876488140873425479553593597508295299674750,14486836623332191458290523271325176557072260063250466764030358280051240942286,1932726606175618877183776650118686155013167275195994452359992776843317764341,10586981584735794740885178709528523597770788130558769643251430679627096503451,17058731514535449611097320348142652958393616886312564975789110366863616539420,21546144187559470183347034044609056404441744756503592317087407561629774536920,5681882870231768621749544290358493454695957383787481123871436386675876219635,6603033703828934401094376159910456525337139277249114676008536852402499584614,1075347119451441392402288921187671249679641364496638526228862984392689015760,9887880282527621962449293235959776308591956208594163166185549404667941094205,3081779595493746844428351914840666042619592907445560123915127502392400574614,11109844704163389102553826717541117344605357734084342755776036340022417198082,5060345909602600407449982784585458050225699107485058131116856520723613936306,20049893406143885619592680397871697055896501875354968455865404394786911398458,11740809795693360891733016778293494519471041728488086332325924371909574885493,21414777615318644939200434569971788107661288737252832241371433802590137831626,19926309906539946638451151936495517057597377615887396199326446649447508281702,5833294070005894544680949322571753681474561462111500624110195335953784263127,20316262126697618722223967532370347145297985363803056816800332573538115921683,20118897454905330779316757365327082825225674670546613715170828215358297124461,15893782176793316439240260419014348246083695310846638270933249304684265430800,12847296795001788271556697499714377689095182754228824085698104180563585670787,17258109440267943312537478894153608811927087776527641627893802618672319064807,3727185744255496747036491258134142468721926815259510264718979349995349167789,2377620008282598351802066487452475263179928244128123362464911386705146759528,20330733534745333298462159658402131849518313653717741882717272744687077336453,3063488930518144343621406800230347607891775381984489334408858649400823600099,11822391183098027641060542512210687183510613996100060945754635806285989372827,2697686870567304805976687716601580249659499813659634827192211658186812105269,19466890284409856892962357589067669895394760875472697889494886746493744150398,1006970646211395884475799222625896618366447925898943829426435645426534803620,18668143903499292595688863135570950175417970684200058312498191992564173409237,374118929819602952730503470915153310582862106749955863047933775501492632816,8098759627317959799834443934069068232617039455327629644555780572940389866941,5647931789489182000343586961287147762347200093731102535565999902997464444183] ) } - +// noir-fmt:ignore pub fn x5_13_config() -> PoseidonConfig<949, 169> { config( 13, @@ -148,7 +146,7 @@ pub fn x5_13_config() -> PoseidonConfig<949, 169> { [5891205978627836991071144083270417159015157070199928807771268303875194037650,19534191765629085451497649051014772157774065629075791332793195826681584551273,5154833515272483128294702820663628026710043323095920240638701304804298499578,7917593571945709638335150893778153193741477651398934233734658265336884279055,5133163238095742835090645087711007173805146496653007212988348307349716673728,19458003745533910239158707983408152209004063097952693956218574434126899070042,18880819400751577287416293176849355951596193714265500681157024197361640709188,11433257809059443065528679883569438998689217744131300496692049205047550090935,12190874701550908088290603272755607342096152398135156662834905887211629834704,3673886960353993252497154566539843726250940370616316569888448647738018022083,15676037835112699420746702265028664494892600184195941373794207326709270851677,5045635616511022726309482514512221209262777381751689684810362174166837266849,2127981970274354891783037834911068612842150500572698772082540184222710046966,20602209860969247631763456039704661822909928028055826436834118113792574371849,4493454930923344041221912772221535937546211498548091351164191172571413962846,9203273896007845628978022785284502260659411177801743914849998536940830966257,8789969715987458351416076625905723956294447007026950650495844175328857015476,11215930522605102963220331022508304708093835095809374254680583403572809751875,15586225257380986275249577321891268850474446160605827963612996219805386502932,10011841080310254678847831138830289501574615297642717372149423820287945856079,18753960408421275836614693391945489354883623026056573684871883182548779915774,19761678450406536764850099419131825403291221931719095841429266089353917202891,2072721799733232450097521331054430993573774079728747665078766019206508544636,10615297085623730419003352440151421233872764050371800287995783143303761635742,11342862179098306415193268089882628716478112844171129584590093902612740081938,19276661508999391381559540866976056457016683157876039262437370976462342153704,3487982371390545412669202630006964510064537478038100559383689697998101381695,18019611455528497754832260490613820837001396745087990928355304172772344827985,18731969803319425707048526160946688629598037600738751037795347491343115736279,18895516979789867152215547520753345684534505439453679476362827176682322481937,8262582236770254192527817333585360308520228688394271238254948357217070957179,20124670759706967221386035867404978156598790198778905768160002435038055915086,10113512603622787997151768792636528607526786828914243169997168136386113705095,915897670578586705347124681284501818659263249883815809455861196950322359631,4168315355477923626825760085789663510629998017921421169386695143739645254818,13671994112691093230470350971338683534216964112891455368255908216954091232088,16886224211742114996348237388698196253930997227482938831037908300450123060344,3345133367703042017339663005080189359441174937067366586009093723866269451347,21528583089657067992968569213666076092311468898762774519530397406988724032331,15876161034145690426475777675897218203065468785806228994483284137836054650127,11419482087592638487692501143058453465931464811952523437138882421550619359191,4688593371456663565609532492788107789533208004746508669973851893459273665535,1201806670097794327812047975382630669548999745861216990648173033237996826404,4317641195125807665177432835324854194367911827066332519796115671103402289320,7278153623621857829571838333149240184056003767208572498343141321166882833584,5645725384264681461759518050072125001915558414870126637288820197391715227313,7876944044995178879031614460771670730631140542631541219377182212657483769883,1817650660807237476840344988506407016951597837358142384730920692904089879519,5477456541807551375261337022497006230056471139241891672239301675658950367705,8048211508931499636316723219242009338536169470228918968914286373316199192147,11051780522682663717015921863167554166331060525740053284975151807269395431450,13621239165564266256293257623306520070257833884735472109300551735647149439281,2212937635665982737914958126511628913962157442295931340442990688391698941226,15995366165560744217392074544914614299200056620022955679432568011246760194348,8186603384193770310414376291688089375415922904100458138117461272757184852177,19591014640167727612037871145675698427320771791339346286884839214170680861630,6878084246380728147562027775456286883121281123291292075367753371891198993189,2177050211387664317673794964274713735596159455191994291603735988793477650579,19810792753868883549077084303872022596455081266982011682803771833184330522738,7185072414158632003497987061744951789947697798790757573674746012007540132625,12527008463897431318214816404214269326472255194708737027196205809865368523993,6934500447964393691613594947677420114877610140521721836488732706620555412923,9978011727059765171039296158502240318826874847845043732001483806732259491882,21367223873262404675887107131444254925505042466133465670356500592380419754092,12370989539828127569760369184182336850673006315469364895069603190681475159813,4771734208255151020750966033073146490824522462970752283771863328392876062708,13551343845317029011162863399460125746613189002552375164523344552618567494698,8714428409330855425634336943651573814895603648572558273360471650145732556280,1770920281347553432035718101936298919487500537138994976517066719980578590089,3110069281490803391353365800012007306367848815614936878141004366920256162421,587101336788172489216190547515347729725635829809300681040400739386253763168,2745547964008447408503376832407161412155228373377123760513770235899201269964,15688219884606649780982718944113231917978875761031663915052600865004707442286,18825709614401251798160680403375685428394659815656068061728877494732182115807,7344398268236623675422623600003139537460576229211381042555723883054380022043,14666515770263042245313469306170077834894759906373286169967918153150186862642,6262353441640473491135912890626291592970997790093308164286742582769628052614,16647307543328963728423591228360400112670150511841037950484862728187168155597,11187123547390829437191210933751439038277808812390863028310714957203862953416,13431586020033401007013925927716006954532655767977222332198563123215088393612,4290575536028694423523505804878297212249395907285796384174966179335089734293,9525030500997851642842588010076299538258273880797610368114449809143832950303,8240494019366037169932737683997756281590058122972608854062263901069681117554,20634410655079842888667296641045124414486057143740858179591482529433244800210,2021226937398532158458585055746155459624344885692396128118875161667614679890,13363628208058779432402710458326211021009444288989875416757721068391318188214,14662421589311461388753832631349921077594459767269924751258576584313288868105,18478701421001679788418312436274921897007545359172305786472370930338255515306,779644354087716689348274274240595541489283221242495213448957276905050464536,16071592196394048404777963063722475415819376772419538934537115615105548954438,5095096770582161819227893847981354649325178848130636101047350986634230116037,1243295118881144894548654933667320243992122811397983231810580344448403973343,11884934205846782297010667633102865650294795721122133935339824653150509106639,7458968983251027899406062962031140351528726088472453510482489928822496580100,19572605475586099575374380909719328911692508931262625802140140705257944509766,14705309817743162695613012501115465410697971407093611587529338557210155341093,21814585268359946040619047839768523980706543116273413618895661291550785045639,18720305501197276565912107809183977276090965285535057360911917408689742145019,2134301697439195186325742384937390317718398738774895777564128344393744278579,16999326242022117650983709520661797031983791094852258286603416430772587131676,17897483181215416614794986081059087805317610826416633427262022077916365348849,19707797946013555426424189263942163273279448488563211841018471715309464788783,14555678829341308540860562709255991938855501651550888461483653488337939676588,17257409408848021559108687223120061819076248102607600439065783833668882002860,3083159817330696927114122348973911210253613266522114299928693807761894470034,5736074496230638296274343498461296106748247754169694274901381380232637436330,8207744709591183622611260068351833593643143431375276434360211505091128037806,16073710603427960567922233549405442518423088068367439127980767364626490766482,16125801016656798988611163501719363451449395969542389751490084517803061425074,16681204974924630782971582682795720527615927905982945319130944791490607417696,4072675318306311800303326010748274698511258916524447342766005819081244518392,4639558473350853876171991553789446979158416238030006798108198266387155784407,21611752344375994669307116989730257280581712049771305171467376136735830835317,14260028812889714557229612460335412900866192266288236233734870104907234066106,10936007367915129326030460455513265303372033050181411601450223671258879981020,2935032369592212871409648743766195391225915910970902425024269583756879977136,6634946569637959135045435256486295750841113686207268069245788404426148269439,11165382706437522214793349607928919108508947068233467479625942161240196013032,11449774151698349588558943383567398137746718964787475388291636245211033594857,13380655477865684658511486065341626238240224687038830357479380314844874141318,1556090800260299290436338214947407050034615159120446561828975680392439133850,15775229412830292677008903643751483031582598935755329498528261914480871637362,8325948986690458545596228454116700887740572176003019243020371356605705227449,1530006957398320461897940887072398082651602436763497487522949690691142033613,12096799031117418724262752691656478204625211872574986459351576236141568686903,9795222686269696766812901618791046177266354705263547407732303299461050133927,6370027108686216641431817942352503637286925173249339052075608610090399016749,16881432515653361341795686702127944966732199129855247935726797972793170639701,15351738821101585856536273249878864428731819041333447251288973888111661451683,14781212701946742438784746658712056984412254191444809612525158953148214912100,8091550554023025707193058566806958042583606199181127012808071174695106343115,20490495862854672187041438553984493686275844004543178578410057111061213880755,17273768908086623408127314492263145283983205996943328025810362733169697859553,19294495315219029609698328900049261980545541811825479502505060031138576089112,21659964890056395567978937545379633715401240283937936880886676845913261767053,17982445074266408124204445317785538167802060185652418682509052997213396963809,5844393214733022541634389892381973171593154485646342141850588851005973351855,18594392739980641449638044568401634303115397702236811642652121212412266849233,8182160648431978634742268417253967926524505311200391645921674911687111696608,11615953679796573972512524871850400010935503185676276201708450621253942540441,21529769273680682324960067458105490598252059794192747768640910191459525561125,20132110404365493609540330952369583903023878161175287878881490874880122068662,3315629685104800403477925330007368560121731964009894641262206418774875779654,20760167657218552641600617661638902204729190730886821404831449731791027856388,1071944235595105837840075721866496337725631499557288435858051131598364359180,4555500238184379140256400675916267083899817767012366155141824954325999920862,12550383095401941417929336389002623533497339330808819244458405679309028814897,16242206659396631583090203067480642438705316999988728264056381863300603790054,9739751068073084582742270086389269366580429568378316378361121134559060472609,16116599372526867528428771037225046273420084760475362036998100512782645537424,1491702476187736766465155485454380021314952117101776564498935819251125640550,15487639992401023512588653485898591177260483949656489128772103961337143916568,271607781293753174262565976623664759968566553298322241892863651425822643900,19977950168772761551778240748644447848771422612925087742515420134526515662483,1983058998587842721058540590280805932874010898105761473162166721490888500174,16107724245058262116195892590046753877901405295502298275519986777803068771465,15598969808860428995774387003121151871293432204528482957206560135604646381090,10303850219152079194793643117738367623863138704730923818757626414538626924093,18042134015692222011976424010811982750427479608456170876100049843530175591980,11698490610713203406365860893495577403678312400711273827266244766764136895745,15094763799279956189651458728729592947034549021140257103479085265792492443257,430096731859098382312819496464652103427606481282347941948051379574546904741,13960717870097098006695192936395126361902142536383841733120824678277505383661,4016844697779547662080765040347308557842613782172342555085194018348439875647,21390612758814913695838461279472506230937295081984131634720827665924667792338,15210153052017283712229693210655704356560541803226219169450332030313730637768,1405020343631287949667260064722407285384539868534544303707265307694982887517,923081188208761071201163943024810005498690637139303388717205039798310044759,11733793144318360060340673323677375331041661345320756410073354731608712531433] ) } - +// noir-fmt:ignore pub fn x5_14_config() -> PoseidonConfig<1092, 196> { config( 14, @@ -159,7 +157,7 @@ pub fn x5_14_config() -> PoseidonConfig<1092, 196> { [6418344278839121997761558068555633277874924383297235060428040203550148460392,8184778893153361724502825398680471446632259194563037088246379746010351701224,16103007220917684483813510789286348056519805127857943417823167430289370248882,1664056765289606259902279533842090994664529145577166075019619213360544081038,8189267971733078428327714274800548471520787418839983750528172780925243373109,20200362011107872066803394413626937903139046091127740529060907959370256880701,20173744990845412211550008592188171997284132875646553363208340317991304601908,6100976759548353184263451545777211359935324012594548692714862113681123862281,18589557631793259794347972680714314322014920073994928130094285735070065431315,774191617468212021433032703138192471679212014828288788368078839883023639562,20846157077077136618808870082870348881758556999252332666235423866411633465885,179369838162302125553370844232732082673907343764950159722856079645852949296,11918621764929568738238867861947162353407822663185301208219638335882724852664,11892816132266551039449220442540498829071526084314780371963132054098089857199,8372083054789567618141127024727893763407629214826505908070525202510871464376,16053969929668995455194287538126250235271805322133461918670713060143921845064,2376335354846722834191665301267088635977856417140218787958824096999457654386,8473768787638105406889032631028566536048259675966039382891971280359035809717,21341339254986951084972542739281440827262568377712659704364142966685544694259,17589661461505870684154172724042456165609752814624225501433267429299923279866,15569410058783548405562051853887675489795673100717406458705097884992918832740,17136771849960699223133648686528512780844440317239376836819594891344485260741,6846911134505306255484642794298233221271816466086606204236441947984501580805,6155197242495613968880604860842601809115711093712877692064968695514089066009,19128637117872288039529749360298403408432890998345732113683578733270478526860,13897081066927368111242039741190751095002227555149381235627883407347099966197,15568696369607733677931070776042128239961624292553408918258251667007167792827,4872469898347155985390501972210222637651779849978701189099596399070936407527,15828528305683107589096901962734302130704783164486093165237194118210566499447,10871050448146531061933214597828428556087596885695624079458134367495768692641,12715634392841723603484337993449575047813504874083783048519693646075495401499,12461797447292058643518857326956961860724022201671935652194772338021756072767,7893478478385050482361413970069327892342442172936930424757486435631374257835,13837601157198138379089270567935062044589875195895421018230835162664685103799,2902437942374588332095798046833013227638771976745087670719351344275677524328,15243444720000907684100993103252257759861356192301299607302082943722781818072,13807772002950549127635782715429970069282430778664455286304012934232212216437,3330690659470353458591000516836956263198779643900957759109026769401030561064,9121369550752168091283493588432030055987339875340008013960004670271046125246,6735940425069065421825600687003545396352913420833444906054707032006918504438,10202597085447755780667010145999569476263425973948073114389503196598866401333,5502428069812047253902185475715178213199056100606031376530298129227524479345,16644412428296109976288812904703533310452124314681543539244699753829624611041,1464363769917768267070780357984170193149530071521363359029977430003041058712,6585015011013232733155666746473112211355795487658434466373981554623709413097,4801399347914387190330170488585953929447785020623558112311440395749307391856,4112082032915966312546686950757741516554419896344654985273514512341960565972,21751105223203500709422523072334627517145925318798961657655356624798705469220,5444707496026644829581718915396971639630623832272466243662913303978147462160,5176202236175268355216491019205403607765794084697970681965844070084688885903,9306814982626014542830328909308268815941037317672165275254890008767120833129,18534005003473959617581160840952814838772020918476059581821124675494141739706,6315286473605163880327953940950267064586093973100720152185112301408202766527,1300066066523772310953083996541204931152213396378337235691979863222476540925,5067928636570884230858740896001720688497565237268231912398775294420405805509,2247332707031505717534336329466562637772796336116582429349574314234357562544,20247738241445291688801934041857783193064556313940428743035963593744371184825,18242310613256758222060583109097399506427347785291803988073944852458874238653,5027570650503078047623512055050961603632044524914664539379503584245086748701,5171024028215683374631525538977404535998938725569475537905229563957776539718,14944506678316768982115249709678873125670683211913646815567280613875065136559,12712774808537003317921729077604843728755135888798177519726799585299850232729,9704917525949617705578174784620125192847872142914494686332094535178307346294,17607293541936391773356775760016259535976314844718033784671775110177131099056,2540563558441922228123722363766317044293335648393481767268774186670778379682,675334497725789143197575210295522345522852999942555409554666160997486976627,19406946394055111935833464724872576724279555593094398662505995447037826031689,8556081865419484437161415079267380957278647215963771014478927152338629734722,10894080579102201350420363592007910695129177124810422954037601558695648517625,11291505870061211613677608925985023369330908318817731122393740145823745286941,8111345701049008354923033690718534410144029586027127161268652239467844080405,274549942856353845785392053622966579448945647367587770109876363273061435394,4517253471300397604524436610993375842851058850598308811197142784491633632173,752091920065645178354359484693693144698238715470242001046768604290011335506,11638201273705718037686872429810169270152128290712392950719778292205581621583,347106139963113855692776969661437659762102942024424980057845079543094637582,1650860247124995235720423411540903470864782697117302631679816892337391491913,8807792864573824348524944774842835780541376663413796103538010142332713129239,10125706840777901469452374931444076850109537279493387272544675392762656076263,5796395502360267028606772833560634747652475684290748049574810918512176530377,14560087906294745333868694378307270211143393355422503000240374502300675908843,5122547319055760404581514483238475236540700695938727023605315976547513018758,18167310745991466802649320845690518166441060923615799361858509593334862918793,10537655786889979411145772153623144374332103428122704649668615330715372491734,11129217221221505592409814225825346415830118409870141057639470413354985898470,18539905463366886572265160849053355497514707079972544561033138019460289616722,2634262960559341073751666364573144239402802922297326052528609874036724778513,1017221748705774701515487698826243372900579204850532621904642815268966836932,17514607882958712820434977243901228312981191640605665595923587928949930664369,11518730158165740016295488007249832672982237183652963149460237152135828893220,5440554707898671641433725775650782970626686693839748603607869391440450924607,9147974268228093219515993293158817299424235911620662153289209094112083583914,2705991777416683673465834362340927783587369064825521543877658261521166181909,17763220243034576321349123132976335282008457858814906290437636386824597776861,8436811158855395670172615633911662578819734431001698203244903207934616540973,4138616319619099661442960332848564292509386403496259477312793995345740346110,9291305887217504987438822522544685995385674372729325355668719643387679293273,14247130176192495492949419984506575479387281081069847984799112525576996955413,12065917784915207956255864287163607339403293417584561373088222422519855200010,19602746430676351974790620090862300757670420200072717172839368523905726952498,5634613092261261536249683912838127927279222476821160426063089671641025921660,5043354945289735676261322233679902891599697472766188245131942353534121350357,10504830582720502950783794220870443419986496189960249704278002268186024527222,14773755085011014730752864609252484899166588993023999143755304644745097411069,15143011250372146369484566133567610168314155803929775363148643430052742055690,9296771043817098875687880718048618354875037373605143322099708291917193542563,6699308928121904151061270394393246387724926649022798867634982215175491150673,8773562200655600334022608356584787571874596251190350038742467377669146368640,14351113364159322541281738731216101468935785403577478179790191188832046493458,4850132968055386067280912095292570467587181719320385350609813213372507065742,4016458733475657342057293585429845015911706822034026494547861057484844319736,894041043510502707790816962794342134661931379046385946357294445947889380857,6102901509904208647404960172211548023168535043766794923435155807898706549347,10993930772305308408754972248679389846078570700140268311987303413959565163567,11304109937008720250639855591630423562437629896442798574433639679310105935745,2101572929952921976477335632619843501489349436900225186251308254022656908969,13379549674365217138865497711163371499213584223441782700932894243483907931587,14594340674649653462364863346385318403203482098904810919462071947226757935441,10647634642733631076053157841634424396589261258510712678605967658799137793311,16930068860033006574251855928288208559689461032565007963103701897524112820278,17170753006961827437085793102001841977757115057767702296590976802337127094191,1342928489123424058754093123906133488378103161461686346784407392402405815911,355084123756415397117817901422581736826549282147584490336790542339114994995,1823092998982212793902589678970070284970565355035702454684653415443223765731,8048898551230697881244098474076915607341905762324328681953519068200924158237,20856146965109368880184165603695312280799455722407374791306423939515039038196,3432336669019104452964292940253917813738689308738628946720655243686051453920,7245438991832359030357502486353272155562833935372540938834365796871211337300,3373527222057951116939099747150655397463396105930227294848620975346900604136,12572707687046208161448564696692430877391470466184921096766838283998472321208,12384937031493229201662431219560608524659573369707802134091983819133706078063,20462122407152292556380602425948480298757076111535435284512383591498863731385,6622785585380387259638611864923325325049433660844748518649420260935388464763,15605049021670133989806310757216368923392900885847286376362426319164543334301,14810486805240500676478878806350063220126440203863567013665308737654824897393,15365995118119349988306703047684161019037838200991362610041019844939301169864,6214064907470154787016516294417895267553707205697453843662274325114029144555,21692877109550228305351038417910800050989918141485758185602644390604582268196,7958034635501608074408556743462969750498597833797740641656952760348926890967,3158783210920420629823137370399691077131051120551658723733852791768119909942,18819671751132769006885776104610704012597692175792895108910904654781356258396,4790325452934584098003515312147561388538271922609950099121379835100064976005,20767398895337785696143628393192433940154143348446221959395714109953426025406,21100955173515864394919601160078443835098475047602620649008862351655083694950,8821416529246363042674973639302381036248538012124317741611227124444469290957,11914021995756592924439683950035443074155751236836696847913625157420325157778,12885168008148287764892654933214399102034605991806678959486007885552095995306,4425275709248360981167156075250953689813562430283330510520431316578062369047,18741351324856319300007832572892392651059227679283122747711533395263296376480,684786537545646459534722549414114801405982388707719975074226812265976115381,13474309605538568830758681457803561340228343878559353019653388997246494295147,3099805728977762711509412402176547022850118685798164610570416531465753528610,5600770441217208920894248156825173605916487562076226390167638135518086562704,20319458329312269677818220957673767032133429098791178878849925747919552800984,14900034607445803864669093098274289660238359682591825230729114910199159461945,8290880045417869099036293157381173265982569186829040493570954991061128070937,8462436298566072387124764625279911648753174589013128335782578822029407672023,21859976115370951722195695482147975930683297060804395404861331672395447064815,14955925753372802734448760267566451635799685206346879293698701403481312089613,4065981601972608953318716423564125873552717375448854762316325928896715511302,16523330234791629267329601436136683980570251446067965291433875700044665982992,4829516041540259457263557932051130738530942234255982016822863700315113125159,2798840870433591285859944008589519120500790120158397573735407833376475300691,13606709616318037902590277227595176470474803011913892797662975188860939656033,18594031070203820621139505381680984797252179318940256457018473319622484612714,301595919185954926511829797241004376609778538475902874115890821742528188064,13821866899865257052128875138353714301663063129600329885914206051645789155403,17834817495579398016717972195069792832976969906967797534885124084571666971093,4636638693344568063056245513561087534038777759740617868439601311740450428791,19461094558355290408553329139619939302588770167904059927666632659470708174566,21540578068459849172758651661944081878533817564350404794583097681041474789761,14656354515483866868842463518575118611017107704362419507056354562832024225447,343560765432454876700403976911389497782754407830340801930660700142029455668,11849359483183996767521484728570765305101196328390648813094255236259946055317,19924264286421201319107239943837407504286665549555105416180422159851955997381,17166797941774367858319514708612731492719223682833034509589752159955652705269,214236542688014950402766598120744795751883810511956979430464011049570919618,19396313302865541199110558245182888004201133198902041449761385765703954241755,12933296125492490585010683271492258153065303286717891025958189212827073719981,17844270568289843619005627429285364222068221173113885235581641198349558307966,10272636157097124940050637562161546985351212351240072791897429490752295849402,5635761628763643716582314870927054669889487541831762994265390120663404976213,1986614715532243876888195532508093896345436225715262830320266933005235142097,1081989267417492031457620947123272024310181199896785177670601875483149154563,4271010751492446271792663900865386872716262596127435260947966701647960153580,9432817034096362918055925335622289410018247097406473925807967486887418646785,8420506466048434939907866067225441403679080978454172178355845135440301602325,7476612931957868870953074766426582066042735713430654491467754928300129405389,7004218213610744415525118134908394594325377744218316765510260162880307132371,7571768879245095309014348656876595924444469219593531275918644914891061799835,4094897072683886403820666572344492999293005026807228977160362626188210714131,16648450944544843693538650431603587114533063135176857105384828552675810607958,12887042974366913908128212909540148628955501312789089034196573637089727885967,7707639242815954375609957852547086529799646052590213478924819089112009057667,8823950326593148986044014943552213420762296615584865468926316064433145020153,3784973153813546220636380916429273484146041804997715013288159720673291711004] ) } - +// noir-fmt:ignore pub fn x5_15_config() -> PoseidonConfig<1020, 225> { config( 15, @@ -170,7 +168,7 @@ pub fn x5_15_config() -> PoseidonConfig<1020, 225> { [1954546571818731885139861264947334230782822161673023234242993080695489129982,11606713580838194823093847718802359011098299538034455148401855555744041817997,21778217939341959600865514937973379081571132553754734185669152755967486158807,11867012199835162777599593543744285374463489953452947402200134749407575327780,20668200962959535110219664454556867828577715202494491079283962871771719016091,6796938349934826085352626361055311106987991567096993611616805270698773290279,15108030096316731537404525399718062561401239877230837132486990179727134215091,18618583058942935584876943765894457772128324732451762769633954204661267055617,7446958258820445329937058505234183740111199633995331064868799738609505041620,11019126795578266009911151080068316016022306110283709712693862589215772062237,17644961526468872013219663511656737898249108220341985100127433673616476030536,4959721361611533340499147366149623398780635086479466110353420780375692399477,18273613083607267201259595982191169247452947601227995394305633285537292365096,17816466502776842735116945485728134149282831962573761460376746436502757322332,7013781340485780306773324480395548266877763825891494701746512901494705653158,7793291197073594006386853421213450159077336220644997691715731402410704643042,3426005025972529257284910903433598760993095858232060658495826014698591260944,18530832095369567225742997294004908129637537286260217494648426754251364141983,16489909564793485793960504581924093693287639849995832883358263301067754354184,15126602449686250365534081130480301443166072957206187316416707568927051456663,13994979972845996867477162556668014834350043400046615820474382058282820089898,17892071176071030024436108339592708638442586845389229765280031864359446154887,7094246519433675669226318744483462997736245331529142696208838903133391196837,19739600791550679646703071148379836779124671330492407813260108679076122705926,16577895124793812992345966235533166228538388644746952252700985971901794098608,2190990407832635064016354900528055762572032133913345251583721394536626731922,10838969594099257399038118686024400001327577210604256394537002295046250661365,13742554186879139633322968994905507641568437399912823098239782636831322642395,10281113667801091149613944447670705624056560574926411753502305328318932013688,7661208680673970050246952651218127022141152720979640414729369551173790735959,14369836811580283035547554195559038793886958236571577920508487931208924192768,20603628573396476191496332378884772502350107937108583985752646932901407759112,19296916296835469264085474516279583782033370007674993417080564950885860980156,10983867448590555143664432588641225682254935452824608025544914671100236945380,5670198946055747149234813634846142209283829958947146164536023332201358566553,4904816432035963931263837796941455228547544800276020247096183162764093041386,928528370618860212551901809222389226336726628142306562102221490519648216649,8727385187994811157471310113729025912812882704232858255495018737569420129281,19909768217191699902186248006262494556099457367519802119733085801884256380544,10635786582281955931244778086998962127059196955758207056871772748744817883737,7140512340052162441606422433836236465795273624186668144911701254961330905493,16598081311443832517669265039250197623929992506944409626575335140315057620768,2339664320384903939910962081546057089170206846484766939921698239663651706239,425509623704802982425483674266195224640999670982140442030650575449074971057,7922384239142329258156226873732902413897900318612725000714450267548570680404,8178140403014386057685967488315772252114289881535707170540858306748328725322,12689293740944871195190670877158259851710828253354810002997981152414697198513,13670630626216376948528966598720909229691593992164633421606526176324419533442,20189490101967313329851160663874367593390331759675962821030507426149184002493,18209972608416650990264895614325602746017028678399567737887116829945804399280,20353660437114078502000672122042327871511027701339587880609263231648053792209,367135858451744056025051491593060073950844607000402056456474235270560576836,13355850760886700974133527239382497141869096511168824351814359808886023658462,7206193356029734986150290058613471641978817208643432940709861990432648635433,7885684183122679587266799938650213096329650494585142531776846669540995068168,19085115218990181267812208821832153255121894513890241319104580206329327134131,16305675470941528258170184941405206862153955794946952667798249341324791515500,15443626257895746936982356461453477742473783071787883800166168668037169561924,101832047855527584987088220264952346019960111874606050409415217845556024488,10576438072746903138917852030571732352003417543540340689583487864994727144138,5996861730264922256270512962050361669936822432104376503237345294243995854540,14877973900502178557219336745361213333854789301797456671201806787562463919326,14807962843542542498914061591358875654692300327506360640837865566998761281322,3133673265931719924452668737189159279894652423873815799856403146721022028744,2314426743898183021393131908284299082806555710249089245305873178073379019830,15353836455896084897563929713128028858175788390437902641700134508986437653318,5529981971838869469294842442312128910934708838384001405870007618574232226406,21863108219378799978996648633069571801923287451100447450849597846874069699478,6773528450923012634292634195479655092490402578779439394568805920957004744133,12150245180431051120309675366247495517352377611113958096501103925281912163211,11142442323884902255425165263749428309435092933107089893872191462936441527962,7030165611221942623542847326918501014233687676615371955108018311000952911338,14168907664945894221515023422776939138433274836712427741726190314020662482321,17973846874050037633502661848899122581090847479984048542694367819419188584711,6612448947387099268202244798863603173886774177350810153571814261011002084641,20765273984039816245168454930434370234220284726385931011063596091927027011108,12525833775624943075128880966259784896817535866921245846013552547690890352574,18082141488353658073882233625595393585704703572017716887747923068948432979709,12080205172928213829055364897249628749790838461826174687455161036760925324146,10426041417079669712788047630796875947997831039494087898318197116078426849054,18333367395418670733687742418586004501344157225223371831515062599898496336393,10666844346085567030848134043176991777319226647942683934134661343455999941894,20287202184725945519955164847740850432153598475156573942705745729215691030796,17942851314410450183054332374663618442963349517519641485232231950262698445043,17672277011389568686180232934337352157780343745417630591806280730146798908966,17416106918062278234521335281965623696779795380548750331807903068461573518054,15034390385078628923681181367678507353936042776187855843799428131823528700439,15016371809918204032764565101078018512566551812562861502095795302834732872947,8176229788878503959342848267153225222150151339952249831413185552792554528595,14202549166569309182319866775579092322766621157492056208423752359103429675445,6628758202046565882882491271332141326521031973243028104017889062740759748530,20267845326067450413789379016153439637066264448919236391605812427944953078755,2438946774028723892708023594952994993532105735189593503088246493623252811398,5327774123437518227973303235331602588839413198088244869937007412210139714640,16416517260868931624699960600760845305546648577328049221217547593071007584547,21691457642736313179352706050711464825492028639914839210493298427277168769684,17369736170805089474636304643282290719726533149056710536120639858255935606857,19460761623902421883797374762298555710671254062576987287084819867262496770119,19770570144034267396127078712986043464609355920552337517533085194608634179666,20904722049832148410244764905538463264520496768863784169293376826852051688706,6086931305514615639236334006857789100145606465861722355610937306339550862,5885641636117295888159072068000551173102681944020015073964039109891861226751,2197549059218467728366947205357858398035068309306368786367182781869500529089,18571065033075196607590252486530861399537536653506142751073877421696969841444,8754088881400442345643534933850221698544089985357770542959718766123813634810,13673463077059539437815915980077307152850526782227553623693374041649724049605,827897346385894242944663854685785871137033256170575635435612086616249561082,3256718342276213157296321691616951565542440296040693556287210483669841487973,18851058760089844863118102177423730353882359970674430675542303019981882750705,21009037983427297652279654800570889577926790955118786173230430780907667982896,19370673591737489444054265538393258291592098201577177240415593550679982651270,9712794467513451079466753095103777002587307366322848872714822737566534970868,2452976395290300719873209484043914405675637974162415011707015440506646332236,13967023770779438454858978860214792451127045212657472381516830319420403024355,18974770134907327058718913691556562240688992993972407935785848010954975834526,18005343276101020422248769804338953747590444642920980587346957205121649916277,5364199751574723768938730543610903684616886041855996090009230701935892264768,16915141432748433783158989990154900013143930156431056052460984382677436665679,9810457740455050658326943855759399108575402539560713791636000764640385927272,15711844859260073612371012979328688796642677336582424352155989490394966892994,2523486975208775388230636032695576725855997180931786065064150527465407276212,12939257203114853364537111886847673104871159136302860798643783368852456402126,18563343508729873190283517746040347988882591986176993103658794343898711153424,9139767925154848725661711816797304370425590863714334419686930754659416933343,15630326979358561783620795846763021145439701823262337294600523076394775855291,16709031855693747432049197217266634836607267701623669179857743766059308291076,11081746589259753124653594380015131650915622160245647873370327872758282529429,10263829532434991046602117509549967441368717347217075372460446855507340910410,923380097607272775621985864770232207712801803675470117823528453022294342573,7060362012752050086965449046391069479205357779670943566418766734533864254186,4238871118210220589598309748597547342336859622832314796736348778105851398663,17520061366255155846404852213753339526277619564174678951991892080505590972066,10513625869281904114245087023227471195681135249236672625281292889978751612829,8435396899666453466602702234562279601174578748121165208762270334814881381944,8088078454252433245088686773582075061475116946251984942060002979516553775360,2719987334353537600366656327639544587227927648913835976421439609622334518069,1024019320641379568207362641296952564452568447918936948059464814762366331275,13889412498086825909291896540147715217051215696137185869382874120375855480535,16901630530096437974516169843541514517956751790577876352535912471650304576719,10977539500432168331426791033212854950231005312634634920276038346698892818211,3226460659346175003896135924099734866664778523605375090881255390738403665617,9695421696482260394078309163365413177132015345359377667904366174083251929056,11269053203885423427900382169641426379373759430258387104391167619152696936070,5178750298399029508026924620615685679610392082191932524033828050686124044833,12845878982355860044505488053971997443594073436267126888909625977253125523142,7530981388399357124357431126610695946065175975095472306777796169245607001944,14058213441446348117716607452759269076404820355922112411973297063005877380478,825603012201903073682942337154197674883919500964784037574585377691889312422,10236993586198323123785803013039327931978354285685191819502917433935835639701,9438970111160688934509448828104684236155844660381402912193342504181825365420,11536612122721678319037657954738688943272460041908847457419482683492719528721,4048128893355211133472225346691072554088570917135573376272009214966234274059,17007960555125781716346334106074020327440615260084049810189285619997415816473,2935744638594795881476272405224480626548498961519135317809162650064622710267,6384493312721061401062408865799313573644091862395937725107886310975229942194,10507848115923740198082149097677194763453026968238422206438345199258995348681,18755782391252715265425541321566381935042481942506333926799033963914433188574,1622030934879728521636669415221999170954870898240640125007128754133416241951,19178897048453000979590659690957596324038669245300140765620928017217201486492,7668471074291870526245483897884601792626426080083647233981123797699500787980,17022938204221917796509718984925895198444138607270396412440297468084153383727,10938747411001421463106680010228586254730710894241856448408311145676137003709,1892143994611253681927160695719312882099525827316460372080933907151205825399,2626413664304179483436880400231214693597358131317388676910101259191110264005,10976814250018194880310517382191223839713741375476951941358522267556104616194,3267603976137604608815546917515683877598008503122930381370588099122094818035,18223585230504941070194267966378685287221743128395324427323638965512681791787,4055897021092860484143383650117982675609656498724344612791022670810747280835,18652001434191198724037217430343155151673545332667032591923572773249520166995,1179210983342192637294098069949454912191992256395734070923896011947222260627,4403412539347069757548448548289536146089860634393235869990028179479631393017,18208249577016536190404023195559477353692681610041814639755282640930299265764,5253459060178003600605009461295776576191151024266914967218417406063967602725,2110599375707753504956307604156004992055199034205281989577749327575131764193,16838175205667561737978735977781331049290662487428014461885404122880770700959,6473428079010461623647807107937762759737150259352991014918746820779470984847,8337370031139132243770630686523670334344396638842630818638144451253681713442,5852133535345551978469538570221409138541345120679970583582105205614182914641,7693908046708935218171096369565374697059710647347392990894755587360287791527,6754690467826351700887172852005234976131445583530162984365436173814346372178,4362899351088205531982963806583486557201252717995038448293398829823910923472,11518397041006514564038599401506526387562942749501723393674197214904315107893,20606341697536003623317613291213380804130123512962185582210369767659416485838,16897394754877405156789353426985842311670174197348619627467370676352261158652,11049995264887964858828368499123384474282091734658191426291499678845498016770,18903841016151023909305743424460730902070062204415137089939274033985227379247,14501632343069777665672565757138143573066425682965558756989443143462299059377,11936194426294671569251421865691095594275214629276606276242590758676139955663,8684782852463301178275527204056308121145836348455196441596832143888384190591,13840275015334112173632265864573045139112521216777064496416258170300441524371,8976112149735004651499648151657522459186187854485087924493254571044062238478,2557541446593153253492913007582627823644717754910327615163106890559828872362,17214289010670114093415697072867115184169717632618753776383803280726887828982,9277044732799923560347274951803854995664839245943597020159605756847120319168,8665104485244718969383349524127237156930430459852710098382428996861193438718,2966017993337369327831105148290320997881600321998609267125699685969931023637,20703140915572601301330743722461592884427012015286406537986295678495182028439,12415056396133226456247587270673507158810318408454307171336801889305959276558,14096884501745579659192341381525893498221351476730589189812251926483574089240,11380799045102603249740262962085086862746282867943901718244205293076495402152,11397463999860523006350413477163951990037313029979805067679629038011006323456,3989254560279764593104713297200294887781503399600736805260233256187721580128,12670526207690537332382598355517632246478654103765566238996179271593311461311,3183711571356392622250181639411196710255078687860623143026450897732409025180,5610846600257417510307213084599977483933519996901968341741797171439650039141,3280606490416179974005759319341626407586508917823138878220428529454629673364,1201982324417186063031536229293952219287079604094432487446300310977814955299,5320694228353869326806779260357179675523748849691821041819016623807887766991,1117900147109997141002482710095589298468009897854242933473562031850755107739,3423874914270570048663861326353594445564054387733265522218157141041404209456,15544724812507000325032356684034497915485954044805225704411638706645864153677,5773122431233952373926318394008190376724448498619094117536291976195311877322,6101823265492636176451963193766486622777300610881276372298697176417958756135,15795396300010870823125638802470599845845464744307444307899702370966825169519,1323789030194931509684647858838729962688902410898850967128356366290242773839,5751046064881673173633677922158261597917572500845688735304279201507132509829,1621252171583823353515150633750260236914561977816101468910968069661001399932,12193773521417435700759146251386454694422997324768376620870510312596267301181,6582582178277044206368630428791785430498389945338461249283089656681050213384,14215781677876725356925186332463972498447213260700771466349787162195918816425,5782842445406193701766362226063474843566378485612132749823957396025995938674,5452153017648783662501027666999013472879951066118424395570738985848450672673,54899108049022846277426184613878330780751769989719315816516065174629128493,8847320923102214377720246218239804718366581789144394009065472718259977212062,7818599458828105010909362503034203380908251186730393621503231459166558068065] ) } - +// noir-fmt:ignore pub fn x5_16_config() -> PoseidonConfig<1152, 256> { config( 16, @@ -181,7 +179,7 @@ pub fn x5_16_config() -> PoseidonConfig<1152, 256> { [19647061463337916460942375553072101475191437675089764130648797272059706835097,2987900412319695329324667493933426290750629320482434345012869808788189293747,14313117549814523542459271158255968194819696107203500245376504355915249564569,635066671179149779961724809079155342626591882143599249747638714005480456001,14160366375280976850992425663667859199067402849136919009370279834492741756927,6973916440684075662378599037972982797550158082488606172483341283171694141353,407790128607292443078618781455551950270304278197678311107891073846005921099,1875793830194257638983834574124736838833728874912304344706772047211830871895,101555677977911034029979807139724697918613026657646487138174278033141465909,13298961474358064737775518932222238976786587146906206646633234612439936576772,6675018665213382228528485041578965344759847379196981998842754547093440230230,5085649234634970209690321129917296688853246686378177913913323311616242468355,10058141944442728296289308385948277117189357184119821310668675797744136293133,20711981720256091912789603700019290285604375596717389895155646132584571552203,20115432152302860531854002084546199214679745925822431241410388037137709465378,19426738311039094155622173280735935805207149231732138766959497422037163547769,7740589787985988848427674257205602851899971532434369842038308874897481875095,11072265639503386933704945672016505140436978537584329931993329650203494086219,6167282302581750408390138662907316184354012779517813053982109604767767995057,14593714320140781629003483490890381863557111469157054599498274206519671343499,17959188687624917851017921366866983692604241271917787434145985166811823698158,10852786592684215415216400376119268936907433212885674472022333115957039052793,15899441678259173360040901233792251513972059637300348276334545233380063193689,3640175378514868793712597306483649195648235320181954901691448087453970656158,19498930515578230344335483600141550927765501643188753803487668144320311818295,4153883544158745158953668931089517690854504894896391299015592025101035411270,19024468701496237603291237797335586206588375930028220273546773163298357041151,7469727364011292433851252680653746774195189525727608179319902706399363717756,2372143841469285674441303263292066347817168610069150223765733476276718069613,2516526351266496289030890575774410993157441063594813081137075222758309555822,20958751338961200084885567700868871946051162714262967700193597995642229058459,9198209373895042225521605474867845062450002141670817279014351290187429107128,543785608759854122795367682791595958842618445464321379849398930724000250504,10214529630060513503750965897811894289300014475522844219670830726679857175601,11576753654045835303746511804171201194442330501175712221979130082457712862265,6214928611453392028562534794962748192402530967301618657847917468183855957477,6248903930557664471829331572570457764958370320737816568669654972084840708363,3521559114442643806761280511561190556015853803605505266866910604261521098953,14207749404758918058098136067805881181486166837455095244160881284733449919110,9959485107346230833915817969343930335833003289106263613217998567268111531500,17002458248120505483758089120825692383088865286608827557586088545674133219848,9310286746554253001882911152696415122865977191166769045081952245779941262056,833245639626789987010046903814146615257437312131003591772116076699143834195,8257332153195419962290907487481324519003765405123021230564312430389478396079,15127724347963527967475442670935452967842333763417615675896327776913208692165,15791631600664089304301903868070551535052107017766205491164731100213785544191,3248589614829341629004884091016822219853816257771914825780122055933452087513,17215199223989028745431952733663229031216291778213241728328297124270973463797,3857684745108028860654397149812523817069881299315264066597992653650257401551,4707785116452305555993924679316564589154347100943642537399862884483438576343,19430682328356065477111453488344441289467658065205729792227680437122893422861,8005988640968242998051528980068908390083328633663970547195021707967989536508,1972474227742829959658839187518313253567182690341134307491795498427960575880,6504813065413498635983080741406156525863657160083764580567056987831449046042,5823311218891803691266204716746992257279538141703406410574718561307174926795,9892303067707797586148875186586047934481214044907972144908705198351662761557,20467423831764780786043971286447965746242601887189594828393353559483921550575,5337137105639218811346004301122986797373254603744281473362301032791465429184,2653918865001450389595199059314513619487087198676481143857196098234024054997,20026090683375374670866007502511215153733777854247692013299401340222837331064,16088029123818655662676092939046004587731443682967462740467056646463545748825,9880178757459464201483861677712096813007025248923714154921858424834034903165,1227858189983101698453184059397045112686910656353893224019532173573557918655,6965709790321124552058584230424761849742693958580766537537673695015364525547,5275724511243540616354496187333612866929959836267482390875038898914899476257,697708336385781014957549769788950342363636191998726381071876409126144042559,7274584324261857876506709208086520820725839679509101845928052585127373751594,1101072498472320542658663987709974387416478403320298285132888772486638626384,17063249509595154712877503960715103016753273139274556931196815282616091591377,20468232842910222775240425801279694589286852891430236774476461428028768660386,10839957331597622631657614186340514237771754591887181416690281526344756522470,1833441125433983427564061829081424752522350755265858559398836992598910515884,18955730579934733484387457001397648556717991843841809299503396866826874046919,8193171082824386660318148864436464606096456472585333569988889002087311061541,6800731829409783994258949782115883803874917294598056504156236185152975271613,4551221506539437319374784319536342657448457365716669137274070321896962382201,3888700085587860510427705376785182344099574784427861867496328978292244934753,8086322087822351497126170321910559010882234382816099821864406027930561491554,13275797274085199955841117698566970822958536692349164078040808025934114965830,11798506987450083560046523556681776539473600393190500985018551824337777992733,2379081429050928317988088394722736405728459402480510127050576787799908525809,2158947553437093664557813698796314628878318098916390925037304154608297340081,11904049624504424229914369023060185670359894203980447724969113153014864088654,21129595246904679929428089867320350013514202309069019924095527072919847726344,10893562472341509760161513998095439702562664638408764329166649578524495942254,14633782125268548143403043594739012390811363821154748677494041549086652426818,18155420130909256009162482779733306385315875131491307204196352931575522168643,12073522950076264054413053294532869251854443128423131910399999522064467473027,1433592116103756425832298952472313408701354429203600638317025112329710147915,2210939565463298865317782595691956567659826882335372151952428383797077275627,17035360868359161456401993589512915729326589319922635525934508061308509305732,21403800287219776827894322644981677663016408317172756418765747341745060868637,13463317002652268594305080031749651114168039804631789430404782211764311412845,19738499492349409431828527491123847227085394983018723982858408988105307624104,2012548380220619299131832783872761872147153098580334235039922730491934764706,3325274441705326523449614352431988173829782789776117744919906973769657338996,5261611144921901341966147913919865209616390993972727644394713260572315512744,18987697050242894331980397947115962487019662790026980590641254086717180862945,8658141027857622941054124779019043605220504649377920644749538450450805414621,11298428708044619749095290390778425959792777464903586113463716315584533582828,6730200291399992595132121834599191803078178940321882359439272645986988925939,16058286461189478903573915480209402516073069688039571574175048313793344696582,9740895146643188739739241045620497326490653096157416163918867637699590812365,17328668678982472669285290349933801381460489699965770954259262923597437466085,21089229510079204828717685354260991995629733636903215847138008238449607565274,20640971546156771190021485453412235742638585574517108137718546522103899393969,14758279983387100491873648446401986574422791750180622274744397880182747812100,1331898546985028774480334813742156878861378216830516346949642945416964272379,6432287430987511826080726363315893796139259314225964668680871966245781390173,16771287021606049252082476128446106722127174299597407353702759915141825150750,8558856604643032676967156921137773032066151674912302830855999926475047747086,3441849687388033123111488396776112259878496892302987380166582753348946609870,20817116194964519717309108464421257788806753886196720998666047916921548668924,19363239836951813038374327912605477961457473367759250309818663552575087804364,8719722538679135055399244869855972116946451760806505569767286592823561841553,18664054074328463099250618543796241821469021451703648566147509976488389212302,14668897608285076749626150823646322752663015099871458303607991619920343960884,8824985320268620533295858061606775496359110158594681923758227994736311199135,10765520116421824752776648993191019870707037690612646148788741126433863060128,20754227554163810768271776561488490692278680037121708279136293739447289576147,8507072847563043340105426835824153184629689984787563844408253684598778757305,6766982373679017786884251724806484438649942596522690604198707242527640673411,3038766798814116247860373387571799940341461487105503437312437210868806237693,16132175023628563044043762398003871532172614031006064729051923614189729264142,15583173149116838843387513514855791665649616393679968646432984027900294981739,19200443718712964237956082975258333421930476944060656325774330146577168149713,14490821043935432280588585568226041328772039440696419883978899443298638245193,1261830229525183456874822855513761625054204680497477037321364189175040481068,6528746667003363057717101918351735481714469206031070610241614606650021871543,16147698956945808666133328464174436996026072559773234518262594815923002983587,9020387669972688980419006674825908656426016085797207362353154226605692909040,6727316761823910734900206867002954254557029243225097482815337322560175181198,10066421681146255853671223544720366622786875122426340101570461526567311479729,18114193263469715956238812322551819970497722041025850638963351240642707536449,13327552382593937204593701292574430198134175441510741573417228229955049364251,2372604211171385703747757710474646305749482500024237878826421281702483230858,13257727745849193909326785093877285673934675536283265665870765530981203548766,6028193081122651452411463574343231811776375151328081689399842891316362242212,8508301356193721985012355411615100178521599009635936162890863637274261948848,19464559199695905284994131173285166577427724356611906328878634139911049316349,11574946347736941315258330071986157639717219704847732435648573723449097294965,14316018291870434740761571976364226850140038868497601980741769481529398163257,10918196690875147279977362872452345319770767457845834002916792583407449275430,8977373069224380198540140180493576791843577554452269707469880849832228035023,748498829648879147053737200607377785638767247375633990031472844537260809404,7873158704115081877804196477528352958470140833786962209738121862287852609943,8630532424574483719830065132415752445222218233997041715460638881404278125797,8690582614704926771670051368117061261335922283383440650770249469863376973533,11095347717221488007795836937657301037546485308926406743891578760518489637433,14135401679286508502504277387212121656373093920904597158275723422439876100612,14738090907871182095556666808390406734966899260337679732930591106508814238308,69949271807030541733792162811562320986072778465870031251424993196153906266,1261108319753649612663311207745706802298135850234573661502446278242936235395,16817683438765699400477322528948826720336276287491287100775393652707943792575,18841362612982270174762542916999427955157117780377439797570032391179795654286,21870116979686159000730008975387147484906370787640570497473602061164852395071,2765949947644452455039725847864010340741814376903283748968022076584286340602,17243705140322781483942034937718263695017457618400778609034996357553437986248,13677914966377093417490296499705767815775553283213762175449591670735007344873,13297897273167025228957171745153893110275891317806768533464851402665750442708,13343269561671098171091946421541340634645677702710756455899883309946421878045,14317554923995329326292532110843156058636017277221221405605647959782965284991,2449835610256525707119222686954432076774548565002604197859382557987062142872,17311927259294224200654531686487034697399582221230204382526629700762752029323,15886029754147081563564215095016637219622964863827251334461319377673888336370,12975391569205596000382467418571211360327385366404855968892273321920864753986,5192224731376769981697271181929966876988577937843948018413420047649317448463,10676192139479409715075805869252336543157972214291179434959380291895052573000,11177450837775344504988539319102121281143354970746599512770721409890402968920,4593200667847399069176143966880767249193687931869738276411303724780636851859,11038090380551563944847929106606106685586830480239388947878234434263502089528,3953526418885419728011595573117200571065709475826662733812952860173033412620,11423581837569206292763368836201420979900393158634684009052097987935130296343,20821758092880168608657749212670937227806187953778513378055795779476865339010,18497750301637542715216545677959957759969933594321504330433834545748130561538,12908315310864070359072899712184126229744818024807969170422172983759986468742,18124554128224712379655197019948407579501104121202515283344405665022477997811,20982975342803604005070898815103511622812678185245827078739170834137855132820,269825514811016046965635325890713556615518696022373524499024558861784638050,3147172016143608266119085281262979524079358702373693860744797997889998689295,14386832245166477008833710911810567249931220515383598373556096298357174022469,4556487278328022691163443795787718624849832853076824895328263286768388362379,12261472135716169178595791281788338424856082203277018628926152780653238868197,3899423277681311798156637809536718065846612626667684730473026778811334914007,19506309861341587023369919042973949592579256277585657370274971571040135953685,1364959409282923580897524375843789492029158451437094417717346158650761726050,16825446178437335546349323854223244861262257417842514939476542139147191650927,8507209116997169365742612629060440573797814488088100151461758543065101868641,15267004752470933248572062004321128218304784520473623806984809921883550707694,676031704648473427598859615894926588607941948575683685792835248653139785855,5619669402121492986528563034254744932241765329516105050276049374453441613893,14704798323824402102639327448519792804756861685698966598005087155126928897024,16320067378138810368504584396122999292945236808095532790918287639367557973453,8146733655224190459272793912328710535983522769849572460217349885461291275505,1038180418056776651442944028459510265058633383281360520702142043667403503844,19104250152149288692194160087229108962380481983770051876357439473931889382526,7003760916474780870091321276888809099928758016210575511830123521067523691017,10460150809039904156668983747345347198316841366879181914914418086579576664491,15677112907432790716289265075133862681087874169637399306212310599581157175963,15326287388823547786897864243344800490244989953594543352512215080754525987008,3009920542142872962638960374061083879344081833005888204328736035225746795718,1804978488347291728619316877980070589260679228487014904460247370976082660690,1328483773995482788116589592947585572244503408960547493086897090179230375909,5730439196427856076422854580234519707227885379777920110477133774925338997125,12981431367443547352573507131765244291012615436617972351790438163822109185806,4832711978673748239567077367987729540684018769513731999388791063624971084279,19167638139894327951096186708600927728591679782746822664161578344690189946483,9333793061773227893961520586484148770892826436173136355616167263506645189532,21458443518750111068075382716496819469049134888053123021475459386077573760694,10205061553685164402371459751106832224694007401400200656551443744478399832956,9830442925198991171494436686328858756494894392913894165312258843542937207416,13609869649628867442619044498926584416410429910199812031508542862339177409898,842857359216662427573900948838829890161571314532391785590044951074431433210,6704851129269714864143856350805682503777715960622547687053167421313207852468,20114446898395957281817578351485444375476540075666338352767091837280210668931,6130491715603374999851365684496448519606340852139128448851532580625582546602,15813600594451539718733724931622603275717510629305297903420212550967482486778,21327142130781371825633810115678136219928778056926678460292750153897861437357,4961568602907543961625596532526706517274095072299784820035412496941108876522,9960714813540172203971946479714057278358565379915043327324100653488017320531,19766028424299726292403979387148081559608033800073407130824876437622345769610,19128679427621049663909949398415698465159247423858348746959133844645715231748,5570166864868188450021144960131468276106515498742461735810689530781856406802,11574972995586621052272541749980259251569951388173301707052886832340902170154,20877646438494519923058752260065237612204466401313282232221152388173388627982,5249150519585813956946898091205522450918428396100844955321690157312140444303,2017741632554727420098342601911590665808744692822556685407780092354922864904,1195760854074467363227832424961613965990883686618742557387108941759791735821,11466582138640916980683611003811079018804741425452823176665968956853901549307,10985903304141344987201754580174851046824447026961915755527591886735857840658,2130569969210610976943124127703960718576010294778156297713757734434872381369,10738808247531379378397673739325665568136689079862172683794674460448121540040,20614646033198180892625991863201166456931543657809805208583071176938057085966,565997125213498936861304726982380864240733960104507001725677609359585569840,10632097546602816816944445466416073366486654512740953706603375905768461201631,12929362833112356946255271584627031609627907912912902502403907291451582319157,1034235212357952436868793031480652544314617407845212103021627643626485031876,19390762319422155950976700977771604452581304443563816543281343170335005291057,10630153844633439282958810722979033212891017579520387012386923832074337305798,14190876500956732147461925775340768352695586121304109940717530850819588911999,18722506055380266423054060346625995391170752586033471909467419883841861306716,3056819986793075694786756176651004538794778835114033048299678024064951583754,4672570536584218848208255703572454924953635491594309524306431682544106754221,17351556719883029551473146382008643929874047263147825865359162665615894766393,15361589507494181649833267508353254535596250253216356073840778948791727807159,13693471199005207103868448237123737586403755421081623632730820742927025187060,17755277847125531485682000612777686738631414648862078678723432159826928724703,5078737090654746516628738054730387217943533822956354885634428155918832329055,12147601749747781924069337935019031145159705806951967042421913575214356549816,14365231440612787726412058658929032228572314258997026523542183583106877612565,7278303658563994843919131396912585917500535615791945995381401546353032136647,16203755920169126984249498560164803107868240707492521482933949021054510520315,6791925607504018751125155518211487306271141824074365658905258365090537532910,13823494237593720607868138054959291887740146822262268248432322209124930846096,11009501160902109690977091445438703229756969339078969536565574715162502634351,14720462490975063947234490477382491041961626472580003583159938559677559185952] ) } - +// noir-fmt:ignore pub fn x5_17_config() -> PoseidonConfig<1292, 289> { config( 17, diff --git a/noir_stdlib/src/hash/poseidon/bn254/perm.nr b/noir_stdlib/src/hash/poseidon/bn254/perm.nr index 8b2f93c2d92..890f54fdb3f 100644 --- a/noir_stdlib/src/hash/poseidon/bn254/perm.nr +++ b/noir_stdlib/src/hash/poseidon/bn254/perm.nr @@ -3,6 +3,7 @@ use crate::hash::poseidon::bn254::consts; use crate::hash::poseidon::bn254::permute; use crate::hash::poseidon::PoseidonConfig; +#[field(bn254)] pub fn x5_2(mut state: [Field; 2]) -> [Field; 2] { state = permute( consts::x5_2_config(), @@ -11,6 +12,7 @@ pub fn x5_2(mut state: [Field; 2]) -> [Field; 2] { state } +#[field(bn254)] pub fn x5_3(mut state: [Field; 3]) -> [Field; 3] { state = permute( consts::x5_3_config(), @@ -19,6 +21,7 @@ pub fn x5_3(mut state: [Field; 3]) -> [Field; 3] { state } +#[field(bn254)] pub fn x5_4(mut state: [Field; 4]) -> [Field; 4] { state = permute( consts::x5_4_config(), @@ -27,6 +30,7 @@ pub fn x5_4(mut state: [Field; 4]) -> [Field; 4] { state } +#[field(bn254)] pub fn x5_5(mut state: [Field; 5]) -> [Field; 5] { state = permute( consts::x5_5_config(), @@ -35,6 +39,7 @@ pub fn x5_5(mut state: [Field; 5]) -> [Field; 5] { state } +#[field(bn254)] pub fn x5_6(mut state: [Field; 6]) -> [Field; 6] { state = permute( consts::x5_6_config(), @@ -43,6 +48,7 @@ pub fn x5_6(mut state: [Field; 6]) -> [Field; 6] { state } +#[field(bn254)] pub fn x5_7(mut state: [Field; 7]) -> [Field; 7] { state = permute( consts::x5_7_config(), @@ -51,6 +57,7 @@ pub fn x5_7(mut state: [Field; 7]) -> [Field; 7] { state } +#[field(bn254)] pub fn x5_8(mut state: [Field; 8]) -> [Field; 8] { state = permute( consts::x5_8_config(), @@ -59,6 +66,7 @@ pub fn x5_8(mut state: [Field; 8]) -> [Field; 8] { state } +#[field(bn254)] pub fn x5_9(mut state: [Field; 9]) -> [Field; 9] { state = permute( consts::x5_9_config(), @@ -67,6 +75,7 @@ pub fn x5_9(mut state: [Field; 9]) -> [Field; 9] { state } +#[field(bn254)] pub fn x5_10(mut state: [Field; 10]) -> [Field; 10] { state = permute( consts::x5_10_config(), @@ -75,6 +84,7 @@ pub fn x5_10(mut state: [Field; 10]) -> [Field; 10] { state } +#[field(bn254)] pub fn x5_11(mut state: [Field; 11]) -> [Field; 11] { state = permute( consts::x5_11_config(), @@ -83,6 +93,7 @@ pub fn x5_11(mut state: [Field; 11]) -> [Field; 11] { state } +#[field(bn254)] pub fn x5_12(mut state: [Field; 12]) -> [Field; 12] { state = permute( consts::x5_12_config(), @@ -91,6 +102,7 @@ pub fn x5_12(mut state: [Field; 12]) -> [Field; 12] { state } +#[field(bn254)] pub fn x5_13(mut state: [Field; 13]) -> [Field; 13] { state = permute( consts::x5_13_config(), @@ -99,6 +111,7 @@ pub fn x5_13(mut state: [Field; 13]) -> [Field; 13] { state } +#[field(bn254)] pub fn x5_14(mut state: [Field; 14]) -> [Field; 14] { state = permute( consts::x5_14_config(), @@ -107,6 +120,7 @@ pub fn x5_14(mut state: [Field; 14]) -> [Field; 14] { state } +#[field(bn254)] pub fn x5_15(mut state: [Field; 15]) -> [Field; 15] { state = permute( consts::x5_15_config(), @@ -115,6 +129,7 @@ pub fn x5_15(mut state: [Field; 15]) -> [Field; 15] { state } +#[field(bn254)] pub fn x5_16(mut state: [Field; 16]) -> [Field; 16] { state = permute( consts::x5_16_config(), @@ -123,6 +138,7 @@ pub fn x5_16(mut state: [Field; 16]) -> [Field; 16] { state } +#[field(bn254)] pub fn x5_17(mut state: [Field; 17]) -> [Field; 17] { state = permute( consts::x5_17_config(), diff --git a/noir_stdlib/src/lib.nr b/noir_stdlib/src/lib.nr index 26cf7a225ee..916e71cb490 100644 --- a/noir_stdlib/src/lib.nr +++ b/noir_stdlib/src/lib.nr @@ -19,7 +19,6 @@ mod compat; mod option; mod string; mod test; - // 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)] @@ -30,36 +29,39 @@ unconstrained pub fn println(input: T) { } #[foreign(recursive_aggregation)] -pub fn verify_proof(_verification_key : [Field], _proof : [Field], _public_inputs : [Field], _key_hash : Field, _input_aggregation_object : [Field; N]) -> [Field; N] {} - +pub fn verify_proof( + _verification_key: [Field], + _proof: [Field], + _public_inputs: [Field], + _key_hash: Field, + _input_aggregation_object: [Field; N] +) -> [Field; N] {} // Asserts that the given value is known at compile-time. // Useful for debugging for-loop bounds. #[builtin(assert_constant)] pub fn assert_constant(_x: T) {} - // from_field and as_field are private since they are not valid for every type. // `as` should be the default for users to cast between primitive types, and in the future // traits can be used to work with generic types. #[builtin(from_field)] -fn from_field(_x : Field) -> T {} +fn from_field(_x: Field) -> T {} #[builtin(as_field)] -fn as_field(_x : T) -> Field {} +fn as_field(_x: T) -> Field {} - -pub fn wrapping_add(x : T, y: T) -> T { +pub fn wrapping_add(x: T, y: T) -> T { crate::from_field(crate::as_field(x) + crate::as_field(y)) } -pub fn wrapping_sub(x : T, y: T) -> T { +pub fn wrapping_sub(x: T, y: T) -> T { //340282366920938463463374607431768211456 is 2^128, it is used to avoid underflow crate::from_field(crate::as_field(x) + 340282366920938463463374607431768211456 - crate::as_field(y)) } -pub fn wrapping_mul(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)) } - -pub fn wrapping_shift_left(x : T, y: T) -> T { - crate::from_field(crate::as_field(x) * 2.pow_32(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/merkle.nr b/noir_stdlib/src/merkle.nr index 0bad55f93f4..9b15fe7313d 100644 --- a/noir_stdlib/src/merkle.nr +++ b/noir_stdlib/src/merkle.nr @@ -1,7 +1,6 @@ // Regular merkle tree means a append-only merkle tree (Explain why this is the only way to have privacy and alternatives if you don't want it) // Currently we assume that it is a binary tree, so depth k implies a width of 2^k // XXX: In the future we can add an arity parameter - // Returns the merkle root of the tree from the provided leaf, its hashpath, using a pedersen hash function. pub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field { let n = hash_path.len(); @@ -11,11 +10,10 @@ pub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) let path_bit = index_bits[i] as bool; let (hash_left, hash_right) = if path_bit { (hash_path[i], current) - } else { + } else { (current, hash_path[i]) - }; - - current = crate::hash::pedersen([hash_left, hash_right])[0]; - }; + }; + current = crate::hash::pedersen_hash([hash_left, hash_right]); + } current } diff --git a/noir_stdlib/src/scalar_mul.nr b/noir_stdlib/src/scalar_mul.nr index f654a810461..37cd935cdb9 100644 --- a/noir_stdlib/src/scalar_mul.nr +++ b/noir_stdlib/src/scalar_mul.nr @@ -5,4 +5,4 @@ // The embedded curve being used is decided by the // underlying proof system. #[foreign(fixed_base_scalar_mul)] -pub fn fixed_base_embedded_curve(_low : Field, _high : Field) -> [Field; 2] {} +pub fn fixed_base_embedded_curve(_low: Field, _high: Field) -> [Field; 2] {} diff --git a/noir_stdlib/src/sha256.nr b/noir_stdlib/src/sha256.nr index d2afd21db8a..4adb93f3848 100644 --- a/noir_stdlib/src/sha256.nr +++ b/noir_stdlib/src/sha256.nr @@ -1,135 +1,128 @@ // Implementation of SHA-256 mapping a byte array of variable length to // 32 bytes. // Internal functions act on 32-bit unsigned integers for simplicity. - // Auxiliary mappings; names as in FIPS PUB 180-4 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) + (a << (32 - b)) + (a >> b) + (crate::wrapping_shift_left(a, 32 - b)) } -fn ch(x: u32, y: u32, z: u32) -> u32 -{ +fn ch(x: u32, y: u32, z: u32) -> u32 { (x & y) ^ ((!x) & z) } -fn maj(x: u32, y: u32, z: u32) -> u32 -{ +fn maj(x: u32, y: u32, z: u32) -> u32 { (x & y) ^ (x & z) ^ (y & z) } -fn bigma0(x: u32) -> u32 -{ +fn bigma0(x: u32) -> u32 { rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22) } -fn bigma1(x: u32) -> u32 -{ +fn bigma1(x: u32) -> u32 { rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25) } -fn sigma0(x: u32) -> u32 -{ +fn sigma0(x: u32) -> u32 { rotr32(x, 7) ^ rotr32(x, 18) ^ (x >> 3) } -fn sigma1(x: u32) -> u32 -{ +fn sigma1(x: u32) -> u32 { rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10) } fn sha_w(msg: [u32; 16]) -> [u32; 64] // Expanded message blocks { - let mut w: [u32;64] = [0; 64]; - - for j in 0..16 - { + + for j in 0..16 { w[j] = msg[j]; - }; + } + + for j in 16..64 { + w[j] = crate::wrapping_add( + crate::wrapping_add(sigma1(w[j-2]), w[j-7]), + crate::wrapping_add(sigma0(w[j-15]), w[j-16]), + ); + } - for j in 16..64 - { - w[j] = sigma1(w[j-2]) + w[j-7] + sigma0(w[j-15]) + w[j-16]; - }; - w } - // SHA-256 compression function -fn sha_c(msg: [u32; 16], hash: [u32; 8]) -> [u32; 8] -{ - - let K: [u32; 64] = [1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]; // first 32 bits of fractional parts of cube roots of first 64 primes - +fn sha_c(msg: [u32; 16], hash: [u32; 8]) -> [u32; 8] { + let K: [u32; 64] = [ + 1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, + 2870763221, 3624381080, 310598401, 607225278, 1426881987, 1925078388, 2162078206, + 2614888103, 3248222580, 3835390401, 4022224774, 264347078, 604807628, 770255983, 1249150122, + 1555081692, 1996064986, 2554220882, 2821834349, 2952996808, 3210313671, 3336571891, + 3584528711, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, + 1986661051, 2177026350, 2456956037, 2730485921, 2820302411, 3259730800, 3345764771, + 3516065817, 3600352804, 4094571909, 275423344, 430227734, 506948616, 659060556, 883997877, + 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, 2227730452, + 2361852424, 2428436474, 2756734187, 3204031479, 3329325298 + ]; // first 32 bits of fractional parts of cube roots of first 64 primes let mut out_h: [u32; 8] = hash; let w = sha_w(msg); - for j in 0..64 - { - let t1 = out_h[7] + bigma1(out_h[4]) + ch(out_h[4], out_h[5], out_h[6]) - + K[j] + w[j]; - let t2 = bigma0(out_h[0]) + maj(out_h[0], out_h[1], out_h[2]); + 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 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]; out_h[5] = out_h[4]; - out_h[4] = out_h[3] + t1; + out_h[4] = crate::wrapping_add(out_h[3], t1); out_h[3] = out_h[2]; out_h[2] = out_h[1]; out_h[1] = out_h[0]; - out_h[0] = t1 + t2; - }; - + out_h[0] = crate::wrapping_add(t1, t2); + } + out_h } - // Convert 64-byte array to array of 16 u32s -fn msg_u8_to_u32(msg: [u8; 64]) -> [u32; 16] -{ +fn msg_u8_to_u32(msg: [u8; 64]) -> [u32; 16] { let mut msg32: [u32; 16] = [0; 16]; - for i in 0..16 - { - for j in 0..4 - { + for i in 0..16 { + for j in 0..4 { msg32[15 - i] = (msg32[15 - i] << 8) + msg[64 - 4*(i + 1) + j] as u32; - }; - }; - + } + } + msg32 } - // SHA-256 hash function pub fn digest(msg: [u8; N]) -> [u8; 32] { let mut msg_block: [u8; 64] = [0; 64]; - let mut h: [u32; 8] = [1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]; // Intermediate hash, starting with the canonical initial value + let mut h: [u32; 8] = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]; // Intermediate hash, starting with the canonical initial value let mut c: [u32; 8] = [0; 8]; // Compression of current message block as sequence of u32 let mut out_h: [u8; 32] = [0; 32]; // Digest as sequence of bytes let mut i: u64 = 0; // Message byte pointer - - for k in 0 .. msg.len() { + for k in 0..msg.len() { // Populate msg_block msg_block[i as Field] = msg[k]; i = i + 1; - if i == 64 { // Enough to hash block + if i == 64 { + // Enough to hash block c = sha_c(msg_u8_to_u32(msg_block), h); for j in 0..8 { - h[j] = c[j] + h[j]; + h[j] = crate::wrapping_add(c[j], h[j]); } - + i = 0; } } - // Pad the rest such that we have a [u32; 2] block at the end representing the length // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]). msg_block[i as Field] = 1 << 7; i = i + 1; - // If i >= 57, there aren't enough bits in the current message block to accomplish this, so // the 1 and 0s fill up the current block, which we then compress accordingly. - if i >= 57 { // Not enough bits (64) to store length. Fill up with zeros. + if i >= 57 { + // Not enough bits (64) to store length. Fill up with zeros. if i < 64 { for _i in 57..64 { if i <= 63 { @@ -141,13 +134,14 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { c = h; c = sha_c(msg_u8_to_u32(msg_block), c); for j in 0..8 { - h[j] += c[j]; + h[j] = crate::wrapping_add(h[j], c[j]); } - + i = 0; } - for _i in 0..64 {// In any case, fill blocks up with zeros until the last 64 (i.e. until i = 56). + for _i in 0..64 { + // In any case, fill blocks up with zeros until the last 64 (i.e. until i = 56). if i < 56 { msg_block[i as Field] = 0; i = i + 1; @@ -160,14 +154,12 @@ pub fn digest(msg: [u8; N]) -> [u8; 32] { i += 8; } } - // Hash final padded block c = h; c = sha_c(msg_u8_to_u32(msg_block), c); for j in 0..8 { - h[j] += c[j]; + h[j] = crate::wrapping_add(h[j], c[j]); } - // Return final hash as byte array for j in 0..8 { for k in 0..4 { diff --git a/noir_stdlib/src/sha512.nr b/noir_stdlib/src/sha512.nr index c565b16c098..ad2926aea81 100644 --- a/noir_stdlib/src/sha512.nr +++ b/noir_stdlib/src/sha512.nr @@ -1,135 +1,119 @@ // Implementation of SHA-512 mapping a byte array of variable length to // 64 bytes. // Internal functions act on 64-bit unsigned integers for simplicity. - // Auxiliary mappings; names as in FIPS PUB 180-4 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) + (a << (64 - b)) + (a >> b) + (crate::wrapping_shift_left(a, 64 - b)) } -fn sha_ch(x: u64, y: u64, z: u64) -> u64 -{ +fn sha_ch(x: u64, y: u64, z: u64) -> u64 { (x & y) ^ (!x & z) } -fn sha_maj(x: u64, y: u64, z: u64) -> u64 -{ +fn sha_maj(x: u64, y: u64, z: u64) -> u64 { (x & y) ^ (x & z) ^ (y & z) } -fn sha_bigma0(x: u64) -> u64 -{ +fn sha_bigma0(x: u64) -> u64 { rotr64(x, 28) ^ rotr64(x, 34) ^ rotr64(x, 39) } -fn sha_bigma1(x: u64) -> u64 -{ +fn sha_bigma1(x: u64) -> u64 { rotr64(x, 14) ^ rotr64(x, 18) ^ rotr64(x, 41) } -fn sha_sigma0(x: u64) -> u64 -{ +fn sha_sigma0(x: u64) -> u64 { rotr64(x, 1) ^ rotr64(x, 8) ^ (x >> 7) } -fn sha_sigma1(x: u64) -> u64 -{ +fn sha_sigma1(x: u64) -> u64 { rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6) } fn sha_w(msg: [u64; 16]) -> [u64; 80] // Expanded message blocks { - let mut w: [u64;80] = [0; 80]; - - for j in 0..16 - { + + for j in 0..16 { w[j] = msg[j]; - }; + } - for j in 16..80 - { - w[j] = sha_sigma1(w[j-2]) + w[j-7] + sha_sigma0(w[j-15]) + w[j-16]; - }; - + for j in 16..80 { + w[j] = crate::wrapping_add( + crate::wrapping_add(sha_sigma1(w[j-2]), w[j-7]), + crate::wrapping_add(sha_sigma0(w[j-15]), w[j-16]), + ); + } w } - // SHA-512 compression function -fn sha_c(msg: [u64; 16], hash: [u64; 8]) -> [u64; 8] -{ +fn sha_c(msg: [u64; 16], hash: [u64; 8]) -> [u64; 8] { + // noir-fmt:ignore let K: [u64; 80] = [4794697086780616226, 8158064640168781261, 13096744586834688815, 16840607885511220156, 4131703408338449720, 6480981068601479193, 10538285296894168987, 12329834152419229976, 15566598209576043074, 1334009975649890238, 2608012711638119052, 6128411473006802146, 8268148722764581231, 9286055187155687089, 11230858885718282805, 13951009754708518548, 16472876342353939154, 17275323862435702243, 1135362057144423861, 2597628984639134821, 3308224258029322869, 5365058923640841347, 6679025012923562964, 8573033837759648693, 10970295158949994411, 12119686244451234320, 12683024718118986047, 13788192230050041572, 14330467153632333762, 15395433587784984357, 489312712824947311, 1452737877330783856, 2861767655752347644, 3322285676063803686, 5560940570517711597, 5996557281743188959, 7280758554555802590, 8532644243296465576, 9350256976987008742, 10552545826968843579, 11727347734174303076, 12113106623233404929, 14000437183269869457, 14369950271660146224, 15101387698204529176, 15463397548674623760, 17586052441742319658, 1182934255886127544, 1847814050463011016, 2177327727835720531, 2830643537854262169, 3796741975233480872, 4115178125766777443, 5681478168544905931, 6601373596472566643, 7507060721942968483, 8399075790359081724, 8693463985226723168, 9568029438360202098, 10144078919501101548, 10430055236837252648, 11840083180663258601, 13761210420658862357, 14299343276471374635, 14566680578165727644, 15097957966210449927, 16922976911328602910, 17689382322260857208, 500013540394364858, 748580250866718886, 1242879168328830382, 1977374033974150939, 2944078676154940804, 3659926193048069267, 4368137639120453308, 4836135668995329356, 5532061633213252278, 6448918945643986474, 6902733635092675308, 7801388544844847127]; // first 64 bits of fractional parts of cube roots of first 80 primes - let mut out_h: [u64; 8] = hash; let w = sha_w(msg); - for j in 0..80 - { - let t1 = out_h[7] + sha_bigma1(out_h[4]) + sha_ch(out_h[4], out_h[5], out_h[6]) - + K[j] + w[j]; - let t2 = sha_bigma0(out_h[0]) + sha_maj(out_h[0], out_h[1], out_h[2]); + for j in 0..80 { + let out1 = crate::wrapping_add(out_h[7], sha_bigma1(out_h[4])); + let out2 = crate::wrapping_add(out1, sha_ch(out_h[4], out_h[5], out_h[6])); + let t1 = crate::wrapping_add(crate::wrapping_add(out2, K[j]), w[j]); + let t2 = crate::wrapping_add(sha_bigma0(out_h[0]), sha_maj(out_h[0], out_h[1], out_h[2])); out_h[7] = out_h[6]; out_h[6] = out_h[5]; out_h[5] = out_h[4]; - out_h[4] = out_h[3] + t1; + out_h[4] = crate::wrapping_add(out_h[3] , t1); out_h[3] = out_h[2]; out_h[2] = out_h[1]; out_h[1] = out_h[0]; - out_h[0] = t1 + t2; - }; - + out_h[0] = crate::wrapping_add(t1, t2); + } + out_h } - // Convert 128-byte array to array of 16 u64s -fn msg_u8_to_u64(msg: [u8; 128]) -> [u64; 16] -{ +fn msg_u8_to_u64(msg: [u8; 128]) -> [u64; 16] { let mut msg64: [u64; 16] = [0; 16]; - for i in 0..16 - { - for j in 0..8 - { + for i in 0..16 { + for j in 0..8 { msg64[15 - i] = (msg64[15 - i] << 8) + msg[128 - 8*(i + 1) + j] as u64; - }; - }; - + } + } + msg64 } - // SHA-512 hash function -pub fn digest(msg: [u8; N]) -> [u8; 64] -{ +pub fn digest(msg: [u8; N]) -> [u8; 64] { let mut msg_block: [u8; 128] = [0; 128]; + // noir-fmt:ignore let mut h: [u64; 8] = [7640891576956012808, 13503953896175478587, 4354685564936845355, 11912009170470909681, 5840696475078001361, 11170449401992604703, 2270897969802886507, 6620516959819538809]; // Intermediate hash, starting with the canonical initial value let mut c: [u64; 8] = [0; 8]; // Compression of current message block as sequence of u64 let mut out_h: [u8; 64] = [0; 64]; // Digest as sequence of bytes let mut i: u64 = 0; // Message byte pointer - - for k in 0 .. msg.len() { + for k in 0..msg.len() { // Populate msg_block msg_block[i as Field] = msg[k]; i = i + 1; - if i == 128 { // Enough to hash block + if i == 128 { + // Enough to hash block c = sha_c(msg_u8_to_u64(msg_block), h); for j in 0..8 { - h[j] += c[j]; + h[j] = crate::wrapping_add(h[j], c[j]); } - + i = 0; } } - // Pad the rest such that we have a [u64; 2] block at the end representing the length // of the message, and a block of 1 0 ... 0 following the message (i.e. [1 << 7, 0, ..., 0]). msg_block[i as Field] = 1 << 7; i += 1; - // If i >= 113, there aren't enough bits in the current message block to accomplish this, so // the 1 and 0s fill up the current block, which we then compress accordingly. - if i >= 113 { // Not enough bits (128) to store length. Fill up with zeros. + if i >= 113 { + // Not enough bits (128) to store length. Fill up with zeros. if i < 128 { for _i in 113..128 { if i <= 127 { @@ -140,13 +124,14 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] } c = sha_c(msg_u8_to_u64(msg_block), h); for j in 0..8 { - h[j] += c[j]; + h[j] = crate::wrapping_add(h[j], c[j]); } - + i = 0; } - for _i in 0..128 {// In any case, fill blocks up with zeros until the last 128 (i.e. until i = 112). + for _i in 0..128 { + // In any case, fill blocks up with zeros until the last 128 (i.e. until i = 112). if i < 112 { msg_block[i as Field] = 0; i += 1; @@ -159,13 +144,11 @@ pub fn digest(msg: [u8; N]) -> [u8; 64] i += 16; // Done. } } - // Hash final padded block c = sha_c(msg_u8_to_u64(msg_block), h); for j in 0..8 { - h[j] += c[j]; + h[j] = crate::wrapping_add(h[j], c[j]); } - // Return final hash as byte array for j in 0..8 { for k in 0..8 { diff --git a/noir_stdlib/src/slice.nr b/noir_stdlib/src/slice.nr index 249c39d3ae7..ca06e2aae44 100644 --- a/noir_stdlib/src/slice.nr +++ b/noir_stdlib/src/slice.nr @@ -1,4 +1,3 @@ - impl [T] { /// Push a new element to the end of the slice, returning a /// new slice with a length one greater than the diff --git a/noir_stdlib/src/string.nr b/noir_stdlib/src/string.nr index 8b0c02f3dd0..e402abf9ab6 100644 --- a/noir_stdlib/src/string.nr +++ b/noir_stdlib/src/string.nr @@ -8,4 +8,4 @@ impl str { pub fn as_bytes_vec(self: Self) -> Vec { Vec::from_slice(self.as_bytes().as_slice()) } -} \ No newline at end of file +} diff --git a/noir_stdlib/src/test.nr b/noir_stdlib/src/test.nr index 18446a4ef85..47b31f4acea 100644 --- a/noir_stdlib/src/test.nr +++ b/noir_stdlib/src/test.nr @@ -1,17 +1,17 @@ #[oracle(create_mock)] -unconstrained fn create_mock_oracle(_name: str) -> Field {} +unconstrained fn create_mock_oracle(_name: str) -> Field {} #[oracle(set_mock_params)] -unconstrained fn set_mock_params_oracle

(_id: Field, _params: P) {} +unconstrained fn set_mock_params_oracle

(_id: Field, _params: P) {} #[oracle(set_mock_returns)] -unconstrained fn set_mock_returns_oracle(_id: Field, _returns: R) {} +unconstrained fn set_mock_returns_oracle(_id: Field, _returns: R) {} #[oracle(set_mock_times)] -unconstrained fn set_mock_times_oracle(_id: Field, _times: u64) {} +unconstrained fn set_mock_times_oracle(_id: Field, _times: u64) {} #[oracle(clear_mock)] -unconstrained fn clear_mock_oracle(_id: Field) {} +unconstrained fn clear_mock_oracle(_id: Field) {} struct OracleMock { id: Field, diff --git a/package.json b/package.json index 47c77ffa945..0e86b100b7c 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "tooling/noir_js_types", "tooling/noirc_abi_wasm", "tooling/noir_js", + "tooling/noir_codegen", "tooling/noir_js_backend_barretenberg", "acvm-repo/acvm_js", "release-tests", diff --git a/release-please-config.json b/release-please-config.json index ddf6ff7b3a9..afc0bfd420d 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -24,6 +24,11 @@ "path": "compiler/wasm/package.json", "jsonpath": "$.version" }, + { + "type": "json", + "path": "tooling/noir_codegen/package.json", + "jsonpath": "$.version" + }, { "type": "json", "path": "tooling/noir_js/package.json", @@ -45,8 +50,8 @@ "jsonpath": "$.version" } ] - }, - "acvm-repo" : { + }, + "acvm-repo": { "release-type": "simple", "package-name": "acvm", "component": "acvm", diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 63f41db96a1..b6f7edc4bde 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.66.1" +channel = "1.71.1" components = [ "rust-src" ] targets = [ "wasm32-unknown-unknown", "wasm32-wasi", "aarch64-apple-darwin" ] profile = "default" diff --git a/tooling/backend_interface/Cargo.toml b/tooling/backend_interface/Cargo.toml index 587dcf41005..14b1609dd4a 100644 --- a/tooling/backend_interface/Cargo.toml +++ b/tooling/backend_interface/Cargo.toml @@ -32,4 +32,4 @@ test-binary = "3.0.1" [build-dependencies] build-target = "0.4.0" -const_format = "0.2.30" +const_format.workspace = true diff --git a/tooling/backend_interface/src/proof_system.rs b/tooling/backend_interface/src/proof_system.rs index c4fc6e743e5..95da1462d4e 100644 --- a/tooling/backend_interface/src/proof_system.rs +++ b/tooling/backend_interface/src/proof_system.rs @@ -23,7 +23,7 @@ impl Backend { // Create a temporary file for the circuit let circuit_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = serialize_circuit(circuit); + let serialized_circuit = Circuit::serialize_circuit(circuit); write_to_file(&serialized_circuit, &circuit_path); GatesCommand { crs_path: self.crs_directory(), bytecode_path: circuit_path } @@ -57,7 +57,7 @@ impl Backend { // Create a temporary file for the circuit // let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = serialize_circuit(circuit); + let serialized_circuit = Circuit::serialize_circuit(circuit); write_to_file(&serialized_circuit, &bytecode_path); // Create proof and store it in the specified path @@ -97,7 +97,7 @@ impl Backend { // Create a temporary file for the circuit let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = serialize_circuit(circuit); + let serialized_circuit = Circuit::serialize_circuit(circuit); write_to_file(&serialized_circuit, &bytecode_path); // Create the verification key and write it to the specified path @@ -130,7 +130,7 @@ impl Backend { // Create a temporary file for the circuit // let bytecode_path = temp_directory.join("circuit").with_extension("bytecode"); - let serialized_circuit = serialize_circuit(circuit); + let serialized_circuit = Circuit::serialize_circuit(circuit); write_to_file(&serialized_circuit, &bytecode_path); // Create the verification key and write it to the specified path @@ -174,11 +174,3 @@ pub(super) fn write_to_file(bytes: &[u8], path: &Path) -> String { Ok(_) => display.to_string(), } } - -// TODO: See nargo/src/artifacts/mod.rs -// TODO: This method should live in ACVM and be the default method for serializing/deserializing circuits -pub(super) fn serialize_circuit(circuit: &Circuit) -> Vec { - let mut circuit_bytes: Vec = Vec::new(); - circuit.write(&mut circuit_bytes).unwrap(); - circuit_bytes -} diff --git a/tooling/backend_interface/src/smart_contract.rs b/tooling/backend_interface/src/smart_contract.rs index 08f67e7b9bc..5dac57c4072 100644 --- a/tooling/backend_interface/src/smart_contract.rs +++ b/tooling/backend_interface/src/smart_contract.rs @@ -1,4 +1,4 @@ -use super::proof_system::{serialize_circuit, write_to_file}; +use super::proof_system::write_to_file; use crate::{ cli::{ContractCommand, WriteVkCommand}, Backend, BackendError, @@ -16,7 +16,7 @@ impl Backend { // Create a temporary file for the circuit let bytecode_path = temp_directory_path.join("circuit").with_extension("bytecode"); - let serialized_circuit = serialize_circuit(circuit); + let serialized_circuit = Circuit::serialize_circuit(circuit); write_to_file(&serialized_circuit, &bytecode_path); // Create the verification key and write it to the specified path diff --git a/tooling/bb_abstraction_leaks/Cargo.toml b/tooling/bb_abstraction_leaks/Cargo.toml index 86164ba11c3..972c78831a7 100644 --- a/tooling/bb_abstraction_leaks/Cargo.toml +++ b/tooling/bb_abstraction_leaks/Cargo.toml @@ -14,4 +14,4 @@ acvm.workspace = true [build-dependencies] build-target = "0.4.0" -const_format = "0.2.30" +const_format.workspace = true diff --git a/tooling/bb_abstraction_leaks/build.rs b/tooling/bb_abstraction_leaks/build.rs index 8d490416094..fe6861a80b8 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.11.1"; +const VERSION: &str = "0.12.0"; const TAG: &str = formatcp!("aztec-packages-v{}", VERSION); const API_URL: &str = diff --git a/tooling/debugger/Cargo.toml b/tooling/debugger/Cargo.toml index 1f9a54b4fe8..53c71754da4 100644 --- a/tooling/debugger/Cargo.toml +++ b/tooling/debugger/Cargo.toml @@ -12,6 +12,7 @@ license.workspace = true acvm.workspace = true nargo.workspace = true noirc_printable_type.workspace = true +noirc_errors.workspace = true thiserror.workspace = true codespan-reporting.workspace = true easy-repl = "0.2.1" diff --git a/tooling/debugger/src/context.rs b/tooling/debugger/src/context.rs new file mode 100644 index 00000000000..33862ed641f --- /dev/null +++ b/tooling/debugger/src/context.rs @@ -0,0 +1,278 @@ +use acvm::acir::circuit::{Circuit, Opcode, OpcodeLocation}; +use acvm::acir::native_types::{Witness, WitnessMap}; +use acvm::brillig_vm::{brillig::Value, Registers}; +use acvm::pwg::{ + ACVMStatus, BrilligSolver, BrilligSolverStatus, ForeignCallWaitInfo, StepResult, ACVM, +}; +use acvm::{BlackBoxFunctionSolver, FieldElement}; + +use nargo::artifacts::debug::DebugArtifact; +use nargo::errors::{ExecutionError, Location}; +use nargo::ops::{DefaultForeignCallExecutor, ForeignCallExecutor}; +use nargo::NargoError; + +use std::collections::{hash_set::Iter, HashSet}; + +#[derive(Debug)] +pub(super) enum DebugCommandResult { + Done, + Ok, + BreakpointReached(OpcodeLocation), + Error(NargoError), +} + +pub(super) struct DebugContext<'a, B: BlackBoxFunctionSolver> { + acvm: ACVM<'a, B>, + brillig_solver: Option>, + foreign_call_executor: DefaultForeignCallExecutor, + debug_artifact: &'a DebugArtifact, + breakpoints: HashSet, +} + +impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { + pub(super) fn new( + blackbox_solver: &'a B, + circuit: &'a Circuit, + debug_artifact: &'a DebugArtifact, + initial_witness: WitnessMap, + ) -> Self { + Self { + acvm: ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness), + brillig_solver: None, + foreign_call_executor: DefaultForeignCallExecutor::new(true), + debug_artifact, + breakpoints: HashSet::new(), + } + } + + pub(super) fn get_opcodes(&self) -> &[Opcode] { + self.acvm.opcodes() + } + + pub(super) fn get_witness_map(&self) -> &WitnessMap { + self.acvm.witness_map() + } + + pub(super) fn overwrite_witness( + &mut self, + witness: Witness, + value: FieldElement, + ) -> Option { + self.acvm.overwrite_witness(witness, value) + } + + pub(super) fn get_current_opcode_location(&self) -> Option { + let ip = self.acvm.instruction_pointer(); + if ip >= self.get_opcodes().len() { + None + } else if let Some(ref solver) = self.brillig_solver { + Some(OpcodeLocation::Brillig { + acir_index: ip, + brillig_index: solver.program_counter(), + }) + } else { + Some(OpcodeLocation::Acir(ip)) + } + } + + /// Returns the callstack in source code locations for the currently + /// executing opcode. This can be `None` if the execution finished (and + /// `get_current_opcode_location()` returns `None`) or if the opcode is not + /// mapped to a specific source location in the debug artifact (which can + /// happen for certain opcodes inserted synthetically by the compiler) + pub(super) fn get_current_source_location(&self) -> Option> { + self.get_current_opcode_location() + .as_ref() + .and_then(|location| self.debug_artifact.debug_symbols[0].opcode_location(location)) + } + + fn step_brillig_opcode(&mut self) -> DebugCommandResult { + let Some(mut solver) = self.brillig_solver.take() else { + unreachable!("Missing Brillig solver"); + }; + match solver.step() { + Ok(BrilligSolverStatus::InProgress) => { + self.brillig_solver = Some(solver); + if self.breakpoint_reached() { + DebugCommandResult::BreakpointReached( + self.get_current_opcode_location() + .expect("Breakpoint reached but we have no location"), + ) + } else { + DebugCommandResult::Ok + } + } + Ok(BrilligSolverStatus::Finished) => { + let status = self.acvm.finish_brillig_with_solver(solver); + self.handle_acvm_status(status) + } + Ok(BrilligSolverStatus::ForeignCallWait(foreign_call)) => { + self.brillig_solver = Some(solver); + self.handle_foreign_call(foreign_call) + } + Err(err) => DebugCommandResult::Error(NargoError::ExecutionError( + ExecutionError::SolvingError(err), + )), + } + } + + fn handle_foreign_call(&mut self, foreign_call: ForeignCallWaitInfo) -> DebugCommandResult { + 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); + // TODO: should we retry executing the opcode somehow in this case? + DebugCommandResult::Ok + } + Err(error) => DebugCommandResult::Error(error.into()), + } + } + + fn handle_acvm_status(&mut self, status: ACVMStatus) -> DebugCommandResult { + if let ACVMStatus::RequiresForeignCall(foreign_call) = status { + return self.handle_foreign_call(foreign_call); + } + + match status { + ACVMStatus::Solved => DebugCommandResult::Done, + ACVMStatus::InProgress => { + if self.breakpoint_reached() { + DebugCommandResult::BreakpointReached( + self.get_current_opcode_location() + .expect("Breakpoint reached but we have no location"), + ) + } else { + DebugCommandResult::Ok + } + } + ACVMStatus::Failure(error) => DebugCommandResult::Error(NargoError::ExecutionError( + ExecutionError::SolvingError(error), + )), + ACVMStatus::RequiresForeignCall(_) => { + unreachable!("Unexpected pending foreign call resolution"); + } + } + } + + pub(super) fn step_into_opcode(&mut self) -> DebugCommandResult { + if self.brillig_solver.is_some() { + return self.step_brillig_opcode(); + } + + match self.acvm.step_into_brillig_opcode() { + StepResult::IntoBrillig(solver) => { + self.brillig_solver = Some(solver); + self.step_brillig_opcode() + } + StepResult::Status(status) => self.handle_acvm_status(status), + } + } + + 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) + } else { + self.acvm.solve_opcode() + }; + self.handle_acvm_status(status) + } + + pub(super) fn next(&mut self) -> DebugCommandResult { + let start_location = self.get_current_source_location(); + loop { + let result = self.step_into_opcode(); + if !matches!(result, DebugCommandResult::Ok) { + return result; + } + let new_location = self.get_current_source_location(); + if new_location.is_some() && new_location != start_location { + return DebugCommandResult::Ok; + } + } + } + + pub(super) fn cont(&mut self) -> DebugCommandResult { + loop { + let result = self.step_into_opcode(); + if !matches!(result, DebugCommandResult::Ok) { + return result; + } + } + } + + pub(super) fn is_executing_brillig(&self) -> bool { + let opcodes = self.get_opcodes(); + let acir_index = self.acvm.instruction_pointer(); + acir_index < opcodes.len() && matches!(opcodes[acir_index], Opcode::Brillig(..)) + } + + pub(super) fn get_brillig_registers(&self) -> Option<&Registers> { + self.brillig_solver.as_ref().map(|solver| solver.get_registers()) + } + + pub(super) fn set_brillig_register(&mut self, register_index: usize, value: FieldElement) { + if let Some(solver) = self.brillig_solver.as_mut() { + solver.set_register(register_index, value.into()); + } + } + + pub(super) fn get_brillig_memory(&self) -> Option<&[Value]> { + self.brillig_solver.as_ref().map(|solver| solver.get_memory()) + } + + pub(super) fn write_brillig_memory(&mut self, ptr: usize, value: FieldElement) { + if let Some(solver) = self.brillig_solver.as_mut() { + solver.write_memory_at(ptr, value.into()); + } + } + + fn breakpoint_reached(&self) -> bool { + if let Some(location) = self.get_current_opcode_location() { + self.breakpoints.contains(&location) + } else { + false + } + } + + pub(super) fn is_valid_opcode_location(&self, location: &OpcodeLocation) -> bool { + let opcodes = self.get_opcodes(); + match *location { + OpcodeLocation::Acir(acir_index) => acir_index < opcodes.len(), + OpcodeLocation::Brillig { acir_index, brillig_index } => { + acir_index < opcodes.len() + && matches!(opcodes[acir_index], Opcode::Brillig(..)) + && { + if let Opcode::Brillig(ref brillig) = opcodes[acir_index] { + brillig_index < brillig.bytecode.len() + } else { + false + } + } + } + } + } + + pub(super) fn is_breakpoint_set(&self, location: &OpcodeLocation) -> bool { + self.breakpoints.contains(location) + } + + pub(super) fn add_breakpoint(&mut self, location: OpcodeLocation) -> bool { + self.breakpoints.insert(location) + } + + pub(super) fn delete_breakpoint(&mut self, location: &OpcodeLocation) -> bool { + self.breakpoints.remove(location) + } + + pub(super) fn iterate_breakpoints(&self) -> Iter<'_, OpcodeLocation> { + self.breakpoints.iter() + } + + pub(super) fn is_solved(&self) -> bool { + matches!(self.acvm.get_status(), ACVMStatus::Solved) + } + + pub fn finalize(self) -> WitnessMap { + self.acvm.finalize() + } +} diff --git a/tooling/debugger/src/lib.rs b/tooling/debugger/src/lib.rs index 42f447ac857..7c6a9e9f618 100644 --- a/tooling/debugger/src/lib.rs +++ b/tooling/debugger/src/lib.rs @@ -1,293 +1,18 @@ -use acvm::acir::circuit::OpcodeLocation; -use acvm::pwg::{ - ACVMStatus, BrilligSolver, BrilligSolverStatus, ErrorLocation, OpcodeResolutionError, - StepResult, ACVM, -}; +mod context; +mod repl; + use acvm::BlackBoxFunctionSolver; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; use nargo::artifacts::debug::DebugArtifact; -use nargo::errors::{ExecutionError, Location}; -use nargo::NargoError; - -use nargo::ops::ForeignCallExecutor; - -use easy_repl::{command, CommandStatus, Critical, Repl}; -use std::{ - cell::{Cell, RefCell}, - ops::Range, -}; - -use owo_colors::OwoColorize; - -use codespan_reporting::files::Files; - -enum SolveResult { - Done, - Ok, -} - -struct DebugContext<'backend, B: BlackBoxFunctionSolver> { - acvm: ACVM<'backend, B>, - brillig_solver: Option>, - debug_artifact: DebugArtifact, - foreign_call_executor: ForeignCallExecutor, - circuit: &'backend Circuit, - show_output: bool, -} - -impl<'backend, B: BlackBoxFunctionSolver> DebugContext<'backend, B> { - fn step_brillig_opcode(&mut self) -> Result { - let Some(mut solver) = self.brillig_solver.take() else { - unreachable!("Missing Brillig solver"); - }; - match solver.step() { - Ok(status) => { - println!("Brillig step result: {:?}", status); - println!("Brillig program counter: {:?}", solver.program_counter()); - match status { - BrilligSolverStatus::InProgress => { - self.brillig_solver = Some(solver); - Ok(SolveResult::Ok) - } - BrilligSolverStatus::Finished => { - let status = self.acvm.finish_brillig_with_solver(solver); - self.handle_acvm_status(status) - } - BrilligSolverStatus::ForeignCallWait(foreign_call) => { - let foreign_call_result = - self.foreign_call_executor.execute(&foreign_call, self.show_output)?; - solver.resolve_pending_foreign_call(foreign_call_result); - self.brillig_solver = Some(solver); - Ok(SolveResult::Ok) - } - } - } - Err(err) => self.handle_acvm_status(ACVMStatus::Failure(err)), - } - } - - fn step_opcode(&mut self) -> Result { - if matches!(self.brillig_solver, Some(_)) { - self.step_brillig_opcode() - } else { - match self.acvm.step_into_brillig_opcode() { - StepResult::IntoBrillig(solver) => { - self.brillig_solver = Some(solver); - self.step_brillig_opcode() - } - StepResult::Status(status) => self.handle_acvm_status(status), - } - } - } - - fn handle_acvm_status(&mut self, status: ACVMStatus) -> Result { - match status { - ACVMStatus::Solved => Ok(SolveResult::Done), - ACVMStatus::InProgress => Ok(SolveResult::Ok), - ACVMStatus::Failure(error) => { - let call_stack = match &error { - OpcodeResolutionError::UnsatisfiedConstrain { - opcode_location: ErrorLocation::Resolved(opcode_location), - } => Some(vec![*opcode_location]), - OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { - Some(call_stack.clone()) - } - _ => None, - }; - - Err(NargoError::ExecutionError(match call_stack { - Some(call_stack) => { - if let Some(assert_message) = self.circuit.get_assert_message( - *call_stack.last().expect("Call stacks should not be empty"), - ) { - ExecutionError::AssertionFailed(assert_message.to_owned(), call_stack) - } else { - ExecutionError::SolvingError(error) - } - } - None => ExecutionError::SolvingError(error), - })) - } - ACVMStatus::RequiresForeignCall(foreign_call) => { - let foreign_call_result = - self.foreign_call_executor.execute(&foreign_call, self.show_output)?; - self.acvm.resolve_pending_foreign_call(foreign_call_result); - Ok(SolveResult::Ok) - } - } - } - - fn show_current_vm_status(&self) { - let ip = self.acvm.instruction_pointer(); - let opcodes = self.acvm.opcodes(); - if ip >= opcodes.len() { - println!("Finished execution"); - } else { - println!("Stopped at opcode {}: {}", ip, opcodes[ip]); - self.show_source_code_location(&OpcodeLocation::Acir(ip), &self.debug_artifact); - } - } - - fn print_location_path(&self, loc: Location) { - let line_number = self.debug_artifact.location_line_number(loc).unwrap(); - let column_number = self.debug_artifact.location_column_number(loc).unwrap(); - - println!( - "At {}:{line_number}:{column_number}", - self.debug_artifact.name(loc.file).unwrap() - ); - } - - fn show_source_code_location(&self, location: &OpcodeLocation, debug_artifact: &DebugArtifact) { - let locations = debug_artifact.debug_symbols[0].opcode_location(location); - let Some(locations) = locations else { return }; - for loc in locations { - self.print_location_path(loc); - - let loc_line_index = debug_artifact.location_line_index(loc).unwrap(); - - // How many lines before or after the location's line we - // print - let context_lines = 5; - - let first_line_to_print = - if loc_line_index < context_lines { 0 } else { loc_line_index - context_lines }; - let last_line_index = debug_artifact.last_line_index(loc).unwrap(); - let last_line_to_print = std::cmp::min(loc_line_index + context_lines, last_line_index); - - let source = debug_artifact.location_source_code(loc).unwrap(); - for (current_line_index, line) in source.lines().enumerate() { - let current_line_number = current_line_index + 1; - - if current_line_index < first_line_to_print { - // Ignore lines before range starts - continue; - } else if current_line_index == first_line_to_print && current_line_index > 0 { - // Denote that there's more lines before but we're not showing them - print_line_of_ellipsis(current_line_index); - } - - if current_line_index > last_line_to_print { - // Denote that there's more lines after but we're not showing them, - // and stop printing - print_line_of_ellipsis(current_line_number); - break; - } - - if current_line_index == loc_line_index { - // Highlight current location - let Range { start: loc_start, end: loc_end } = - debug_artifact.location_in_line(loc).unwrap(); - println!( - "{:>3} {:2} {}{}{}", - current_line_number, - "->", - &line[0..loc_start].to_string().dimmed(), - &line[loc_start..loc_end], - &line[loc_end..].to_string().dimmed() - ); - } else { - print_dimmed_line(current_line_number, line); - } - } - } - } - - fn cont(&mut self) -> Result { - loop { - match self.step_opcode()? { - SolveResult::Done => break, - SolveResult::Ok => {} - } - } - Ok(SolveResult::Done) - } - - fn finalize(self) -> WitnessMap { - self.acvm.finalize() - } -} - -fn print_line_of_ellipsis(line_number: usize) { - println!("{}", format!("{:>3} {}", line_number, "...").dimmed()); -} - -fn print_dimmed_line(line_number: usize, line: &str) { - println!("{}", format!("{:>3} {:2} {}", line_number, "", line).dimmed()); -} - -fn map_command_status(result: SolveResult) -> CommandStatus { - match result { - SolveResult::Ok => CommandStatus::Done, - SolveResult::Done => CommandStatus::Quit, - } -} +use nargo::NargoError; pub fn debug_circuit( blackbox_solver: &B, circuit: &Circuit, debug_artifact: DebugArtifact, initial_witness: WitnessMap, - show_output: bool, ) -> Result, NargoError> { - let context = RefCell::new(DebugContext { - acvm: ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness), - foreign_call_executor: ForeignCallExecutor::default(), - brillig_solver: None, - circuit, - debug_artifact, - show_output, - }); - let ref_step = &context; - let ref_cont = &context; - - let solved = Cell::new(false); - - context.borrow().show_current_vm_status(); - - let handle_result = |result| { - solved.set(matches!(result, SolveResult::Done)); - Ok(map_command_status(result)) - }; - - let mut repl = Repl::builder() - .add( - "s", - command! { - "step to the next opcode", - () => || { - let result = ref_step.borrow_mut().step_opcode().into_critical()?; - ref_step.borrow().show_current_vm_status(); - handle_result(result) - } - }, - ) - .add( - "c", - command! { - "continue execution until the end of the program", - () => || { - println!("(Continuing execution...)"); - let result = ref_cont.borrow_mut().cont().into_critical()?; - handle_result(result) - } - }, - ) - .build() - .expect("Failed to initialize debugger repl"); - - repl.run().expect("Debugger error"); - - // REPL execution has finished. - // Drop it so that we can move fields out from `context` again. - drop(repl); - - if solved.get() { - let solved_witness = context.into_inner().finalize(); - Ok(Some(solved_witness)) - } else { - Ok(None) - } + repl::run(blackbox_solver, circuit, &debug_artifact, initial_witness) } diff --git a/tooling/debugger/src/repl.rs b/tooling/debugger/src/repl.rs new file mode 100644 index 00000000000..23abe83c38d --- /dev/null +++ b/tooling/debugger/src/repl.rs @@ -0,0 +1,568 @@ +use crate::context::{DebugCommandResult, DebugContext}; + +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 easy_repl::{command, CommandStatus, Repl}; +use std::cell::RefCell; + +use codespan_reporting::files::Files; +use noirc_errors::Location; + +use owo_colors::OwoColorize; + +use std::ops::Range; + +pub struct ReplDebugger<'a, B: BlackBoxFunctionSolver> { + context: DebugContext<'a, B>, + blackbox_solver: &'a B, + circuit: &'a Circuit, + debug_artifact: &'a DebugArtifact, + initial_witness: WitnessMap, + last_result: DebugCommandResult, +} + +impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { + pub fn new( + blackbox_solver: &'a B, + circuit: &'a Circuit, + debug_artifact: &'a DebugArtifact, + initial_witness: WitnessMap, + ) -> Self { + let context = + DebugContext::new(blackbox_solver, circuit, debug_artifact, initial_witness.clone()); + Self { + context, + blackbox_solver, + circuit, + debug_artifact, + initial_witness, + last_result: DebugCommandResult::Ok, + } + } + + pub fn show_current_vm_status(&self) { + let location = self.context.get_current_opcode_location(); + let opcodes = self.context.get_opcodes(); + + match location { + None => println!("Finished execution"), + Some(location) => { + match location { + OpcodeLocation::Acir(ip) => { + println!("At opcode {}: {}", ip, opcodes[ip]) + } + OpcodeLocation::Brillig { acir_index, brillig_index } => { + let Opcode::Brillig(ref brillig) = opcodes[acir_index] else { + unreachable!("Brillig location does not contain a Brillig block"); + }; + println!( + "At opcode {}.{}: {:?}", + acir_index, brillig_index, brillig.bytecode[brillig_index] + ); + } + } + self.show_source_code_location(&location); + } + } + } + + fn print_location_path(&self, loc: Location) { + let line_number = self.debug_artifact.location_line_number(loc).unwrap(); + let column_number = self.debug_artifact.location_column_number(loc).unwrap(); + + println!( + "At {}:{line_number}:{column_number}", + self.debug_artifact.name(loc.file).unwrap() + ); + } + + fn show_source_code_location(&self, location: &OpcodeLocation) { + let locations = self.debug_artifact.debug_symbols[0].opcode_location(location); + let Some(locations) = locations else { return }; + for loc in locations { + self.print_location_path(loc); + + let loc_line_index = self.debug_artifact.location_line_index(loc).unwrap(); + + // How many lines before or after the location's line we + // print + let context_lines = 5; + + let first_line_to_print = + if loc_line_index < context_lines { 0 } else { loc_line_index - context_lines }; + + let last_line_index = self.debug_artifact.last_line_index(loc).unwrap(); + let last_line_to_print = std::cmp::min(loc_line_index + context_lines, last_line_index); + + let source = self.debug_artifact.location_source_code(loc).unwrap(); + for (current_line_index, line) in source.lines().enumerate() { + let current_line_number = current_line_index + 1; + + if current_line_index < first_line_to_print { + // Ignore lines before range starts + continue; + } else if current_line_index == first_line_to_print && current_line_index > 0 { + // Denote that there's more lines before but we're not showing them + print_line_of_ellipsis(current_line_index); + } + + if current_line_index > last_line_to_print { + // Denote that there's more lines after but we're not showing them, + // and stop printing + print_line_of_ellipsis(current_line_number); + break; + } + + if current_line_index == loc_line_index { + // Highlight current location + let Range { start: loc_start, end: loc_end } = + self.debug_artifact.location_in_line(loc).unwrap(); + println!( + "{:>3} {:2} {}{}{}", + current_line_number, + "->", + &line[0..loc_start].to_string().dimmed(), + &line[loc_start..loc_end], + &line[loc_end..].to_string().dimmed() + ); + } else { + print_dimmed_line(current_line_number, line); + } + } + } + } + + fn display_opcodes(&self) { + let opcodes = self.context.get_opcodes(); + let current_opcode_location = self.context.get_current_opcode_location(); + let current_acir_index = match current_opcode_location { + Some(OpcodeLocation::Acir(ip)) => Some(ip), + Some(OpcodeLocation::Brillig { acir_index, .. }) => Some(acir_index), + None => None, + }; + let current_brillig_index = match current_opcode_location { + Some(OpcodeLocation::Brillig { brillig_index, .. }) => brillig_index, + _ => 0, + }; + let outer_marker = |acir_index| { + if current_acir_index == Some(acir_index) { + "->" + } else if self.context.is_breakpoint_set(&OpcodeLocation::Acir(acir_index)) { + " *" + } else { + "" + } + }; + let brillig_marker = |acir_index, brillig_index| { + if current_acir_index == Some(acir_index) && brillig_index == current_brillig_index { + "->" + } else if self + .context + .is_breakpoint_set(&OpcodeLocation::Brillig { acir_index, brillig_index }) + { + " *" + } else { + "" + } + }; + for (acir_index, opcode) in opcodes.iter().enumerate() { + let marker = outer_marker(acir_index); + if let Opcode::Brillig(brillig) = opcode { + println!("{:>3} {:2} BRILLIG inputs={:?}", acir_index, marker, brillig.inputs); + println!(" | outputs={:?}", brillig.outputs); + for (brillig_index, brillig_opcode) in brillig.bytecode.iter().enumerate() { + println!( + "{:>3}.{:<2} |{:2} {:?}", + acir_index, + brillig_index, + brillig_marker(acir_index, brillig_index), + brillig_opcode + ); + } + } else { + println!("{:>3} {:2} {:?}", acir_index, marker, opcode); + } + } + } + + fn add_breakpoint_at(&mut self, location: OpcodeLocation) { + if !self.context.is_valid_opcode_location(&location) { + println!("Invalid opcode location {location}"); + } else if self.context.add_breakpoint(location) { + println!("Added breakpoint at opcode {location}"); + } else { + println!("Breakpoint at opcode {location} already set"); + } + } + + fn delete_breakpoint_at(&mut self, location: OpcodeLocation) { + if self.context.delete_breakpoint(&location) { + println!("Breakpoint at opcode {location} deleted"); + } else { + println!("Breakpoint at opcode {location} not set"); + } + } + + fn validate_in_progress(&self) -> bool { + match self.last_result { + DebugCommandResult::Ok | DebugCommandResult::BreakpointReached(..) => true, + DebugCommandResult::Done => { + println!("Execution finished"); + false + } + DebugCommandResult::Error(ref error) => { + println!("ERROR: {}", error); + self.show_current_vm_status(); + false + } + } + } + + fn handle_debug_command_result(&mut self, result: DebugCommandResult) { + match &result { + DebugCommandResult::BreakpointReached(location) => { + println!("Stopped at breakpoint in opcode {}", location); + } + DebugCommandResult::Error(error) => { + println!("ERROR: {}", error); + } + _ => (), + } + self.last_result = result; + self.show_current_vm_status(); + } + + fn step_acir_opcode(&mut self) { + if self.validate_in_progress() { + let result = self.context.step_acir_opcode(); + self.handle_debug_command_result(result); + } + } + + fn step_into_opcode(&mut self) { + if self.validate_in_progress() { + let result = self.context.step_into_opcode(); + self.handle_debug_command_result(result); + } + } + + fn next(&mut self) { + if self.validate_in_progress() { + let result = self.context.next(); + self.handle_debug_command_result(result); + } + } + + fn cont(&mut self) { + if self.validate_in_progress() { + println!("(Continuing execution...)"); + let result = self.context.cont(); + self.handle_debug_command_result(result); + } + } + + fn restart_session(&mut self) { + let breakpoints: Vec = + self.context.iterate_breakpoints().copied().collect(); + self.context = DebugContext::new( + self.blackbox_solver, + self.circuit, + self.debug_artifact, + self.initial_witness.clone(), + ); + for opcode_location in breakpoints { + self.context.add_breakpoint(opcode_location); + } + self.last_result = DebugCommandResult::Ok; + println!("Restarted debugging session."); + self.show_current_vm_status(); + } + + pub fn show_witness_map(&self) { + let witness_map = self.context.get_witness_map(); + // NOTE: we need to clone() here to get the iterator + for (witness, value) in witness_map.clone().into_iter() { + println!("_{} = {value}", witness.witness_index()); + } + } + + pub fn show_witness(&self, index: u32) { + if let Some(value) = self.context.get_witness_map().get_index(index) { + println!("_{} = {value}", index); + } + } + + pub fn update_witness(&mut self, index: u32, value: String) { + let Some(field_value) = FieldElement::try_from_str(&value) else { + println!("Invalid witness value: {value}"); + return; + }; + + let witness = Witness::from(index); + _ = self.context.overwrite_witness(witness, field_value); + println!("_{} = {value}", index); + } + + pub fn show_brillig_registers(&self) { + if !self.context.is_executing_brillig() { + println!("Not executing a Brillig block"); + return; + } + + let Some(registers) = self.context.get_brillig_registers() else { + // this can happen when just entering the Brillig block since ACVM + // would have not initialized the Brillig VM yet; in fact, the + // Brillig code may be skipped altogether + println!("Brillig VM registers not available"); + return; + }; + + for (index, value) in registers.inner.iter().enumerate() { + println!("{index} = {}", value.to_field()); + } + } + + pub fn set_brillig_register(&mut self, index: usize, value: String) { + let Some(field_value) = FieldElement::try_from_str(&value) else { + println!("Invalid value: {value}"); + return; + }; + if !self.context.is_executing_brillig() { + println!("Not executing a Brillig block"); + return; + } + self.context.set_brillig_register(index, field_value); + } + + pub fn show_brillig_memory(&self) { + if !self.context.is_executing_brillig() { + println!("Not executing a Brillig block"); + return; + } + + let Some(memory) = self.context.get_brillig_memory() else { + // this can happen when just entering the Brillig block since ACVM + // would have not initialized the Brillig VM yet; in fact, the + // Brillig code may be skipped altogether + println!("Brillig VM memory not available"); + return; + }; + + for (index, value) in memory.iter().enumerate() { + println!("{index} = {}", value.to_field()); + } + } + + pub fn write_brillig_memory(&mut self, index: usize, value: String) { + let Some(field_value) = FieldElement::try_from_str(&value) else { + println!("Invalid value: {value}"); + return; + }; + if !self.context.is_executing_brillig() { + println!("Not executing a Brillig block"); + return; + } + self.context.write_brillig_memory(index, field_value); + } + + fn is_solved(&self) -> bool { + self.context.is_solved() + } + + fn finalize(self) -> WitnessMap { + self.context.finalize() + } +} + +fn print_line_of_ellipsis(line_number: usize) { + println!("{}", format!("{:>3} {}", line_number, "...").dimmed()); +} + +fn print_dimmed_line(line_number: usize, line: &str) { + println!("{}", format!("{:>3} {:2} {}", line_number, "", line).dimmed()); +} + +pub fn run( + blackbox_solver: &B, + circuit: &Circuit, + debug_artifact: &DebugArtifact, + initial_witness: WitnessMap, +) -> Result, NargoError> { + let context = + RefCell::new(ReplDebugger::new(blackbox_solver, circuit, debug_artifact, initial_witness)); + let ref_context = &context; + + ref_context.borrow().show_current_vm_status(); + + let mut repl = Repl::builder() + .add( + "step", + command! { + "step to the next ACIR opcode", + () => || { + ref_context.borrow_mut().step_acir_opcode(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "into", + command! { + "step into to the next opcode", + () => || { + ref_context.borrow_mut().step_into_opcode(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "next", + command! { + "step until a new source location is reached", + () => || { + ref_context.borrow_mut().next(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "continue", + command! { + "continue execution until the end of the program", + () => || { + ref_context.borrow_mut().cont(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "restart", + command! { + "restart the debugging session", + () => || { + ref_context.borrow_mut().restart_session(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "opcodes", + command! { + "display ACIR opcodes", + () => || { + ref_context.borrow().display_opcodes(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "break", + command! { + "add a breakpoint at an opcode location", + (LOCATION:OpcodeLocation) => |location| { + ref_context.borrow_mut().add_breakpoint_at(location); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "delete", + command! { + "delete breakpoint at an opcode location", + (LOCATION:OpcodeLocation) => |location| { + ref_context.borrow_mut().delete_breakpoint_at(location); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "witness", + command! { + "show witness map", + () => || { + ref_context.borrow().show_witness_map(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "witness", + command! { + "display a single witness from the witness map", + (index: u32) => |index| { + ref_context.borrow().show_witness(index); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "witness", + command! { + "update a witness with the given value", + (index: u32, value: String) => |index, value| { + ref_context.borrow_mut().update_witness(index, value); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "registers", + command! { + "show Brillig registers (valid when executing a Brillig block)", + () => || { + ref_context.borrow().show_brillig_registers(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "regset", + command! { + "update a Brillig register with the given value", + (index: usize, value: String) => |index, value| { + ref_context.borrow_mut().set_brillig_register(index, value); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "memory", + command! { + "show Brillig memory (valid when executing a Brillig block)", + () => || { + ref_context.borrow().show_brillig_memory(); + Ok(CommandStatus::Done) + } + }, + ) + .add( + "memset", + command! { + "update a Brillig memory cell with the given value", + (index: usize, value: String) => |index, value| { + ref_context.borrow_mut().write_brillig_memory(index, value); + Ok(CommandStatus::Done) + } + }, + ) + .build() + .expect("Failed to initialize debugger repl"); + + repl.run().expect("Debugger error"); + + // REPL execution has finished. + // Drop it so that we can move fields out from `context` again. + drop(repl); + + if context.borrow().is_solved() { + let solved_witness = context.into_inner().finalize(); + Ok(Some(solved_witness)) + } else { + Ok(None) + } +} diff --git a/tooling/lsp/Cargo.toml b/tooling/lsp/Cargo.toml index f6585690985..9e642d5fe9c 100644 --- a/tooling/lsp/Cargo.toml +++ b/tooling/lsp/Cargo.toml @@ -22,7 +22,9 @@ serde.workspace = true serde_json.workspace = true tower.workspace = true cfg-if.workspace = true -async-lsp = { version = "0.0.5", default-features = false, features = ["omni-trait"] } +async-lsp = { workspace = true, features = ["omni-trait"] } +serde_with = "3.2.0" +fm.workspace = true [target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies] wasm-bindgen.workspace = true diff --git a/tooling/lsp/src/lib.rs b/tooling/lsp/src/lib.rs index 6e71f3d642d..79fc544692a 100644 --- a/tooling/lsp/src/lib.rs +++ b/tooling/lsp/src/lib.rs @@ -26,7 +26,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_shutdown, on_test_run_request, on_tests_request, + on_code_lens_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; @@ -66,6 +67,7 @@ impl NargoLspService { .request::(on_code_lens_request) .request::(on_tests_request) .request::(on_test_run_request) + .request::(on_profile_run_request) .notification::(on_initialized) .notification::(on_did_change_configuration) .notification::(on_did_open_text_document) diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs index 633c88b420a..93fa8baf6ac 100644 --- a/tooling/lsp/src/notifications/mod.rs +++ b/tooling/lsp/src/notifications/mod.rs @@ -3,7 +3,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 noirc_driver::check_crate; +use noirc_driver::{check_crate, NOIR_ARTIFACT_VERSION_STRING}; use noirc_errors::{DiagnosticKind, FileDiagnostic}; use crate::types::{ @@ -88,7 +88,11 @@ pub(super) fn on_did_save_text_document( return ControlFlow::Continue(()); } }; - let workspace = match resolve_workspace_from_toml(&toml_path, PackageSelection::All) { + let workspace = match resolve_workspace_from_toml( + &toml_path, + PackageSelection::All, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + ) { Ok(workspace) => workspace, Err(err) => { // If we found a manifest, but the workspace is invalid, we raise an error about it diff --git a/tooling/lsp/src/requests/code_lens_request.rs b/tooling/lsp/src/requests/code_lens_request.rs index 700002d2030..602ed268981 100644 --- a/tooling/lsp/src/requests/code_lens_request.rs +++ b/tooling/lsp/src/requests/code_lens_request.rs @@ -4,7 +4,7 @@ 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; +use noirc_driver::{check_crate, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::hir::FunctionNameMatch; use crate::{ @@ -23,6 +23,9 @@ 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}") } @@ -67,11 +70,15 @@ fn on_code_lens_request_inner( return Ok(None); } }; - let workspace = - resolve_workspace_from_toml(&toml_path, PackageSelection::All).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 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![]; @@ -159,6 +166,16 @@ fn on_code_lens_request_inner( 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); } } @@ -196,6 +213,16 @@ fn on_code_lens_request_inner( 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); } } } diff --git a/tooling/lsp/src/requests/mod.rs b/tooling/lsp/src/requests/mod.rs index 166adb10b5a..b2be24e1187 100644 --- a/tooling/lsp/src/requests/mod.rs +++ b/tooling/lsp/src/requests/mod.rs @@ -19,11 +19,13 @@ use crate::{ // and params passed in. mod code_lens_request; +mod profile_run; mod test_run; mod tests; pub(crate) use { - code_lens_request::on_code_lens_request, test_run::on_test_run_request, tests::on_tests_request, + code_lens_request::on_code_lens_request, profile_run::on_profile_run_request, + test_run::on_test_run_request, tests::on_tests_request, }; pub(crate) fn on_initialize( diff --git a/tooling/lsp/src/requests/profile_run.rs b/tooling/lsp/src/requests/profile_run.rs new file mode 100644 index 00000000000..84888d30ba5 --- /dev/null +++ b/tooling/lsp/src/requests/profile_run.rs @@ -0,0 +1,102 @@ +use std::{ + collections::{BTreeMap, HashMap}, + future::{self, Future}, +}; + +use acvm::{acir::circuit::Opcode, Language}; +use async_lsp::{ErrorCode, ResponseError}; +use nargo::artifacts::debug::DebugArtifact; +use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use noirc_driver::{CompileOptions, DebugFile, NOIR_ARTIFACT_VERSION_STRING}; +use noirc_errors::{debug_info::OpCodesCount, Location}; + +use crate::{ + types::{NargoProfileRunParams, NargoProfileRunResult}, + LspState, +}; +use fm::FileId; + +pub(crate) fn on_profile_run_request( + state: &mut LspState, + params: NargoProfileRunParams, +) -> impl Future> { + future::ready(on_profile_run_request_inner(state, params)) +} + +fn on_profile_run_request_inner( + state: &LspState, + params: NargoProfileRunParams, +) -> Result { + let root_path = state.root_path.as_deref().ok_or_else(|| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "Could not find project root") + })?; + + let toml_path = find_package_manifest(root_path, root_path).map_err(|err| { + // If we cannot find a manifest, we can't run the test + ResponseError::new(ErrorCode::REQUEST_FAILED, err) + })?; + + let crate_name = params.package; + + let workspace = resolve_workspace_from_toml( + &toml_path, + PackageSelection::DefaultOrAll, + 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) + })?; + + // Since we filtered on crate name, this should be the only item in the iterator + match workspace.into_iter().next() { + Some(_package) => { + let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace + .into_iter() + .filter(|package| !package.is_library()) + .cloned() + .partition(|package| package.is_binary()); + + // # TODO(#3504): Consider how to incorporate Backend relevant information in wider context. + let is_opcode_supported = |_opcode: &Opcode| true; + let np_language = Language::PLONKCSat { width: 3 }; + + let (compiled_programs, compiled_contracts) = nargo::ops::compile_workspace( + &workspace, + &binary_packages, + &contract_packages, + np_language, + is_opcode_supported, + &CompileOptions::default(), + ) + .map_err(|err| ResponseError::new(ErrorCode::REQUEST_FAILED, err))?; + + let mut opcodes_counts: HashMap = HashMap::new(); + let mut file_map: BTreeMap = BTreeMap::new(); + for compiled_program in &compiled_programs { + let span_opcodes = compiled_program.debug.count_span_opcodes(); + let debug_artifact: DebugArtifact = compiled_program.clone().into(); + opcodes_counts.extend(span_opcodes); + file_map.extend(debug_artifact.file_map); + } + + for compiled_contract in &compiled_contracts { + let functions = &compiled_contract.functions; + let debug_artifact: DebugArtifact = compiled_contract.clone().into(); + file_map.extend(debug_artifact.file_map); + for contract_function in functions { + let span_opcodes = contract_function.debug.count_span_opcodes(); + opcodes_counts.extend(span_opcodes); + } + } + + let result = NargoProfileRunResult { file_map, opcodes_counts }; + + Ok(result) + } + None => Err(ResponseError::new( + ErrorCode::REQUEST_FAILED, + format!("Could not locate package named: {crate_name}"), + )), + } +} diff --git a/tooling/lsp/src/requests/test_run.rs b/tooling/lsp/src/requests/test_run.rs index 30a3015eb75..962fe99a49b 100644 --- a/tooling/lsp/src/requests/test_run.rs +++ b/tooling/lsp/src/requests/test_run.rs @@ -6,7 +6,7 @@ use nargo::{ prepare_package, }; use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{check_crate, CompileOptions}; +use noirc_driver::{check_crate, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::hir::FunctionNameMatch; use crate::{ @@ -38,12 +38,15 @@ fn on_test_run_request_inner( let crate_name = params.id.crate_name(); let function_name = params.id.function_name(); - let workspace = - resolve_workspace_from_toml(&toml_path, PackageSelection::Selected(crate_name.clone())) - .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 workspace = resolve_workspace_from_toml( + &toml_path, + PackageSelection::Selected(crate_name.clone()), + 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) + })?; // Since we filtered on crate name, this should be the only item in the iterator match workspace.into_iter().next() { diff --git a/tooling/lsp/src/requests/tests.rs b/tooling/lsp/src/requests/tests.rs index a5988b54f06..6b94b921a06 100644 --- a/tooling/lsp/src/requests/tests.rs +++ b/tooling/lsp/src/requests/tests.rs @@ -4,7 +4,7 @@ use async_lsp::{ErrorCode, LanguageClient, ResponseError}; use lsp_types::{LogMessageParams, MessageType}; use nargo::prepare_package; use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::check_crate; +use noirc_driver::{check_crate, NOIR_ARTIFACT_VERSION_STRING}; use crate::{ get_non_stdlib_asset, get_package_tests_in_crate, @@ -40,11 +40,15 @@ fn on_tests_request_inner( } }; - let workspace = - resolve_workspace_from_toml(&toml_path, PackageSelection::All).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 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 package_tests: Vec<_> = workspace .into_iter() diff --git a/tooling/lsp/src/types.rs b/tooling/lsp/src/types.rs index 10f1764c63f..7a50c538051 100644 --- a/tooling/lsp/src/types.rs +++ b/tooling/lsp/src/types.rs @@ -1,5 +1,10 @@ +use fm::FileId; +use noirc_driver::DebugFile; +use noirc_errors::{debug_info::OpCodesCount, Location}; use noirc_frontend::graph::CrateName; use serde::{Deserialize, Serialize}; +use serde_with::serde_as; +use std::collections::{BTreeMap, HashMap}; // Re-providing lsp_types that we don't need to override pub(crate) use lsp_types::{ @@ -14,8 +19,8 @@ pub(crate) mod request { use lsp_types::{request::Request, InitializeParams}; use super::{ - InitializeResult, NargoTestRunParams, NargoTestRunResult, NargoTestsParams, - NargoTestsResult, + InitializeResult, NargoProfileRunParams, NargoProfileRunResult, NargoTestRunParams, + NargoTestRunResult, NargoTestsParams, NargoTestsResult, }; // Re-providing lsp_types that we don't need to override @@ -44,6 +49,14 @@ pub(crate) mod request { type Result = NargoTestsResult; const METHOD: &'static str = "nargo/tests"; } + + #[derive(Debug)] + pub(crate) struct NargoProfileRun; + impl Request for NargoProfileRun { + type Params = NargoProfileRunParams; + type Result = NargoProfileRunResult; + const METHOD: &'static str = "nargo/profile/run"; + } } pub(crate) mod notification { @@ -186,5 +199,16 @@ pub(crate) struct NargoTestRunResult { pub(crate) result: String, pub(crate) message: Option, } +#[derive(Debug, Serialize, Deserialize)] +pub(crate) struct NargoProfileRunParams { + pub(crate) package: CrateName, +} +#[serde_as] +#[derive(Debug, Serialize, Deserialize)] +pub(crate) struct NargoProfileRunResult { + pub(crate) file_map: BTreeMap, + #[serde_as(as = "Vec<(_, _)>")] + pub(crate) opcodes_counts: HashMap, +} pub(crate) type CodeLensResult = Option>; diff --git a/tooling/nargo/Cargo.toml b/tooling/nargo/Cargo.toml index eda15ff2594..f8269459968 100644 --- a/tooling/nargo/Cargo.toml +++ b/tooling/nargo/Cargo.toml @@ -23,5 +23,5 @@ noirc_printable_type.workspace = true iter-extended.workspace = true serde.workspace = true thiserror.workspace = true -base64.workspace = true codespan-reporting.workspace = true +rayon = "1.8.0" \ No newline at end of file diff --git a/tooling/nargo/build.rs b/tooling/nargo/build.rs index cf52e8b2627..4fa7f58892a 100644 --- a/tooling/nargo/build.rs +++ b/tooling/nargo/build.rs @@ -2,8 +2,8 @@ use rustc_version::{version, Version}; fn check_rustc_version() { assert!( - version().unwrap() >= Version::parse("1.66.0").unwrap(), - "The minimal supported rustc version is 1.66.0." + version().unwrap() >= Version::parse("1.71.1").unwrap(), + "The minimal supported rustc version is 1.71.1." ); } diff --git a/tooling/nargo/src/artifacts/contract.rs b/tooling/nargo/src/artifacts/contract.rs index 4f1ae0e10a0..f9e8d45b02e 100644 --- a/tooling/nargo/src/artifacts/contract.rs +++ b/tooling/nargo/src/artifacts/contract.rs @@ -37,8 +37,8 @@ pub struct PreprocessedContractFunction { pub abi: Abi, #[serde( - serialize_with = "super::serialize_circuit", - deserialize_with = "super::deserialize_circuit" + serialize_with = "Circuit::serialize_circuit_base64", + deserialize_with = "Circuit::deserialize_circuit_base64" )] pub bytecode: Circuit, } diff --git a/tooling/nargo/src/artifacts/debug.rs b/tooling/nargo/src/artifacts/debug.rs index d2e2eb9f311..40acc7db8f8 100644 --- a/tooling/nargo/src/artifacts/debug.rs +++ b/tooling/nargo/src/artifacts/debug.rs @@ -1,6 +1,7 @@ use codespan_reporting::files::{Error, Files, SimpleFile}; -use noirc_driver::DebugFile; +use noirc_driver::{CompiledContract, CompiledProgram, DebugFile}; use noirc_errors::{debug_info::DebugInfo, Location}; +use noirc_evaluator::errors::SsaReport; use serde::{Deserialize, Serialize}; use std::{ collections::{BTreeMap, BTreeSet}, @@ -15,6 +16,7 @@ use fm::{FileId, FileManager, PathString}; pub struct DebugArtifact { pub debug_symbols: Vec, pub file_map: BTreeMap, + pub warnings: Vec, } impl DebugArtifact { @@ -43,7 +45,7 @@ impl DebugArtifact { ); } - Self { debug_symbols, file_map } + Self { debug_symbols, file_map, warnings: Vec::new() } } /// Given a location, returns its file's source code @@ -94,6 +96,32 @@ impl DebugArtifact { } } +impl From for DebugArtifact { + fn from(compiled_program: CompiledProgram) -> Self { + DebugArtifact { + debug_symbols: vec![compiled_program.debug], + file_map: compiled_program.file_map, + warnings: compiled_program.warnings, + } + } +} + +impl From<&CompiledContract> for DebugArtifact { + fn from(compiled_artifact: &CompiledContract) -> Self { + let all_functions_debug: Vec = compiled_artifact + .functions + .iter() + .map(|contract_function| contract_function.debug.clone()) + .collect(); + + DebugArtifact { + debug_symbols: all_functions_debug, + file_map: compiled_artifact.file_map.clone(), + warnings: compiled_artifact.warnings.clone(), + } + } +} + impl<'a> Files<'a> for DebugArtifact { type FileId = FileId; type Name = PathString; diff --git a/tooling/nargo/src/artifacts/mod.rs b/tooling/nargo/src/artifacts/mod.rs index d25c65afd98..180a900fd81 100644 --- a/tooling/nargo/src/artifacts/mod.rs +++ b/tooling/nargo/src/artifacts/mod.rs @@ -3,34 +3,6 @@ //! These artifacts are intended to remain independent of any applications being built on top of Noir. //! Should any projects require/desire a different artifact format, it's expected that they will write a transformer //! to generate them using these artifacts as a starting point. -use acvm::acir::circuit::Circuit; -use base64::Engine; -use serde::{ - de::Error as DeserializationError, ser::Error as SerializationError, Deserializer, Serializer, -}; - pub mod contract; pub mod debug; pub mod program; - -// TODO: move these down into ACVM. -fn serialize_circuit(circuit: &Circuit, s: S) -> Result -where - S: Serializer, -{ - let mut circuit_bytes: Vec = Vec::new(); - circuit.write(&mut circuit_bytes).map_err(S::Error::custom)?; - let encoded_b64 = base64::engine::general_purpose::STANDARD.encode(circuit_bytes); - s.serialize_str(&encoded_b64) -} - -fn deserialize_circuit<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let bytecode_b64: String = serde::Deserialize::deserialize(deserializer)?; - let circuit_bytes = - base64::engine::general_purpose::STANDARD.decode(bytecode_b64).map_err(D::Error::custom)?; - let circuit = Circuit::read(&*circuit_bytes).map_err(D::Error::custom)?; - Ok(circuit) -} diff --git a/tooling/nargo/src/artifacts/program.rs b/tooling/nargo/src/artifacts/program.rs index 5988f3f59cb..890b6c55f7d 100644 --- a/tooling/nargo/src/artifacts/program.rs +++ b/tooling/nargo/src/artifacts/program.rs @@ -21,8 +21,8 @@ pub struct PreprocessedProgram { pub abi: Abi, #[serde( - serialize_with = "super::serialize_circuit", - deserialize_with = "super::deserialize_circuit" + serialize_with = "Circuit::serialize_circuit_base64", + deserialize_with = "Circuit::deserialize_circuit_base64" )] pub bytecode: Circuit, } diff --git a/tooling/nargo/src/errors.rs b/tooling/nargo/src/errors.rs index 0c920716f2a..bca8ca24767 100644 --- a/tooling/nargo/src/errors.rs +++ b/tooling/nargo/src/errors.rs @@ -2,13 +2,36 @@ use acvm::{ acir::circuit::OpcodeLocation, pwg::{ErrorLocation, OpcodeResolutionError}, }; -use noirc_errors::{debug_info::DebugInfo, CustomDiagnostic, FileDiagnostic}; +use noirc_errors::{ + debug_info::DebugInfo, reporter::ReportedErrors, CustomDiagnostic, FileDiagnostic, +}; pub use noirc_errors::Location; +use noirc_frontend::graph::CrateName; use noirc_printable_type::ForeignCallError; use thiserror::Error; +/// Errors covering situations where a package cannot be compiled. +#[derive(Debug, Error)] +pub enum CompileError { + #[error("Package `{0}` has type `lib` but only `bin` types can be compiled")] + LibraryCrate(CrateName), + + #[error("Package `{0}` is expected to have a `main` function but it does not")] + MissingMainFunction(CrateName), + + /// Errors encountered while compiling the Noir program. + /// These errors are already written to stderr. + #[error("Aborting due to {} previous error{}", .0.error_count, if .0.error_count == 1 { "" } else { "s" })] + ReportedErrors(ReportedErrors), +} +impl From for CompileError { + fn from(errors: ReportedErrors) -> Self { + Self::ReportedErrors(errors) + } +} + #[derive(Debug, Error)] pub enum NargoError { /// Error while compiling Noir into ACIR. @@ -91,7 +114,7 @@ fn extract_locations_from_error( _ => None, }?; - if let Some(OpcodeLocation::Brillig { acir_index, .. }) = opcode_locations.get(0) { + if let Some(OpcodeLocation::Brillig { acir_index, .. }) = opcode_locations.first() { opcode_locations.insert(0, OpcodeLocation::Acir(*acir_index)); } diff --git a/tooling/nargo/src/ops/compile.rs b/tooling/nargo/src/ops/compile.rs new file mode 100644 index 00000000000..d4164eaa865 --- /dev/null +++ b/tooling/nargo/src/ops/compile.rs @@ -0,0 +1,154 @@ +use acvm::{acir::circuit::Opcode, Language}; +use fm::FileManager; +use noirc_driver::{CompilationResult, CompileOptions, CompiledContract, CompiledProgram}; + +use crate::errors::CompileError; +use crate::prepare_package; +use crate::{package::Package, workspace::Workspace}; + +use rayon::prelude::*; + +/// Compiles workspace. +/// +/// # Errors +/// +/// This function will return an error if there are any compilations errors reported. +pub fn compile_workspace( + workspace: &Workspace, + binary_packages: &[Package], + contract_packages: &[Package], + np_language: Language, + is_opcode_supported: impl Fn(&Opcode) -> bool + std::marker::Sync, + compile_options: &CompileOptions, +) -> Result<(Vec, Vec), CompileError> { + // Compile all of the packages in parallel. + let program_results: Vec<(FileManager, CompilationResult)> = binary_packages + .par_iter() + .map(|package| { + compile_program(workspace, package, compile_options, np_language, &is_opcode_supported) + }) + .collect(); + let contract_results: Vec<(FileManager, CompilationResult)> = + contract_packages + .par_iter() + .map(|package| { + compile_contract(package, compile_options, np_language, &is_opcode_supported) + }) + .collect(); + + // Report any warnings/errors which were encountered during compilation. + let compiled_programs: Vec = program_results + .into_iter() + .map(|(file_manager, compilation_result)| { + report_errors( + compilation_result, + &file_manager, + compile_options.deny_warnings, + compile_options.silence_warnings, + ) + }) + .collect::>()?; + let compiled_contracts: Vec = contract_results + .into_iter() + .map(|(file_manager, compilation_result)| { + report_errors( + compilation_result, + &file_manager, + compile_options.deny_warnings, + compile_options.silence_warnings, + ) + }) + .collect::>()?; + + Ok((compiled_programs, compiled_contracts)) +} + +pub fn compile_program( + workspace: &Workspace, + package: &Package, + compile_options: &CompileOptions, + 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 program_artifact_path = workspace.package_build_path(package); + let mut debug_artifact_path = program_artifact_path.clone(); + debug_artifact_path.set_file_name(format!("debug_{}.json", package.name)); + + let (program, warnings) = + match noirc_driver::compile_main(&mut context, crate_id, compile_options, None, true) { + Ok(program_and_warnings) => program_and_warnings, + Err(errors) => { + return (context.file_manager, Err(errors)); + } + }; + + // 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"); + + (context.file_manager, Ok((optimized_program, warnings))) +} + +fn compile_contract( + package: &Package, + compile_options: &CompileOptions, + 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 (contract, warnings) = + match noirc_driver::compile_contract(&mut context, crate_id, compile_options) { + Ok(contracts_and_warnings) => contracts_and_warnings, + Err(errors) => { + return (context.file_manager, Err(errors)); + } + }; + + let optimized_contract = + crate::ops::optimize_contract(contract, np_language, &is_opcode_supported) + .expect("Backend does not support an opcode that is in the IR"); + + (context.file_manager, Ok((optimized_contract, warnings))) +} + +pub(crate) fn report_errors( + result: CompilationResult, + file_manager: &FileManager, + deny_warnings: bool, + silence_warnings: bool, +) -> Result { + let (t, warnings) = result.map_err(|errors| { + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &errors, + deny_warnings, + silence_warnings, + ) + })?; + + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &warnings, + deny_warnings, + silence_warnings, + ); + + Ok(t) +} diff --git a/tooling/nargo/src/ops/execute.rs b/tooling/nargo/src/ops/execute.rs index cf14934d61e..d7cb44188c4 100644 --- a/tooling/nargo/src/ops/execute.rs +++ b/tooling/nargo/src/ops/execute.rs @@ -7,16 +7,14 @@ use crate::NargoError; use super::foreign_calls::ForeignCallExecutor; -pub fn execute_circuit( - blackbox_solver: &B, +pub fn execute_circuit( circuit: &Circuit, initial_witness: WitnessMap, - show_output: bool, + blackbox_solver: &B, + foreign_call_executor: &mut F, ) -> Result { let mut acvm = ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness); - let mut foreign_call_executor = ForeignCallExecutor::default(); - loop { let solver_status = acvm.solve(); @@ -50,8 +48,7 @@ pub fn execute_circuit( })); } ACVMStatus::RequiresForeignCall(foreign_call) => { - let foreign_call_result = - foreign_call_executor.execute(&foreign_call, show_output)?; + let foreign_call_result = foreign_call_executor.execute(&foreign_call)?; acvm.resolve_pending_foreign_call(foreign_call_result); } } diff --git a/tooling/nargo/src/ops/foreign_calls.rs b/tooling/nargo/src/ops/foreign_calls.rs index 4d20a0bd4f0..6cc78febab3 100644 --- a/tooling/nargo/src/ops/foreign_calls.rs +++ b/tooling/nargo/src/ops/foreign_calls.rs @@ -5,7 +5,12 @@ use acvm::{ use iter_extended::vecmap; use noirc_printable_type::{decode_string_value, ForeignCallError, PrintableValueDisplay}; -use crate::NargoError; +pub trait ForeignCallExecutor { + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result; +} /// 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 @@ -89,23 +94,55 @@ impl MockedCall { } #[derive(Debug, Default)] -pub struct ForeignCallExecutor { +pub struct DefaultForeignCallExecutor { /// Mocks have unique ids used to identify them in Noir, allowing to update or remove them. last_mock_id: usize, /// The registered mocks mocked_responses: Vec, + /// Whether to print [`ForeignCall::Println`] output. + show_output: bool, } -impl ForeignCallExecutor { - pub fn execute( +impl DefaultForeignCallExecutor { + pub fn new(show_output: bool) -> Self { + DefaultForeignCallExecutor { show_output, ..DefaultForeignCallExecutor::default() } + } +} + +impl DefaultForeignCallExecutor { + fn extract_mock_id( + foreign_call_inputs: &[ForeignCallParam], + ) -> Result<(usize, &[ForeignCallParam]), ForeignCallError> { + let (id, params) = + foreign_call_inputs.split_first().ok_or(ForeignCallError::MissingForeignCallInputs)?; + Ok((id.unwrap_value().to_usize(), params)) + } + + fn find_mock_by_id(&mut self, id: usize) -> Option<&mut MockedCall> { + self.mocked_responses.iter_mut().find(|response| response.id == id) + } + + fn parse_string(param: &ForeignCallParam) -> String { + let fields: Vec<_> = param.values().into_iter().map(|value| value.to_field()).collect(); + 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}"); + Ok(()) + } +} + +impl ForeignCallExecutor for DefaultForeignCallExecutor { + fn execute( &mut self, foreign_call: &ForeignCallWaitInfo, - show_output: bool, - ) -> Result { + ) -> Result { let foreign_call_name = foreign_call.function.as_str(); match ForeignCall::lookup(foreign_call_name) { Some(ForeignCall::Println) => { - if show_output { + if self.show_output { Self::execute_println(&foreign_call.inputs)?; } Ok(ForeignCallResult { values: vec![] }) @@ -202,27 +239,4 @@ impl ForeignCallExecutor { } } } - - fn extract_mock_id( - foreign_call_inputs: &[ForeignCallParam], - ) -> Result<(usize, &[ForeignCallParam]), ForeignCallError> { - let (id, params) = - foreign_call_inputs.split_first().ok_or(ForeignCallError::MissingForeignCallInputs)?; - Ok((id.unwrap_value().to_usize(), params)) - } - - fn find_mock_by_id(&mut self, id: usize) -> Option<&mut MockedCall> { - self.mocked_responses.iter_mut().find(|response| response.id == id) - } - - fn parse_string(param: &ForeignCallParam) -> String { - let fields: Vec<_> = param.values().into_iter().map(|value| value.to_field()).collect(); - decode_string_value(&fields) - } - - fn execute_println(foreign_call_inputs: &[ForeignCallParam]) -> Result<(), NargoError> { - let display_values: PrintableValueDisplay = foreign_call_inputs.try_into()?; - println!("{display_values}"); - Ok(()) - } } diff --git a/tooling/nargo/src/ops/mod.rs b/tooling/nargo/src/ops/mod.rs index 491320482cf..34487ed9770 100644 --- a/tooling/nargo/src/ops/mod.rs +++ b/tooling/nargo/src/ops/mod.rs @@ -1,8 +1,10 @@ +pub use self::compile::{compile_program, compile_workspace}; pub use self::execute::execute_circuit; -pub use self::foreign_calls::ForeignCallExecutor; +pub use self::foreign_calls::{DefaultForeignCallExecutor, ForeignCallExecutor}; pub use self::optimize::{optimize_contract, optimize_program}; pub use self::test::{run_test, TestStatus}; +mod compile; mod execute; mod foreign_calls; mod optimize; diff --git a/tooling/nargo/src/ops/test.rs b/tooling/nargo/src/ops/test.rs index d2ef2659e4d..5bfdd6d15d0 100644 --- a/tooling/nargo/src/ops/test.rs +++ b/tooling/nargo/src/ops/test.rs @@ -6,7 +6,7 @@ use noirc_frontend::hir::{def_map::TestFunction, Context}; use crate::{errors::try_to_diagnose_runtime_error, NargoError}; -use super::execute_circuit; +use super::{execute_circuit, DefaultForeignCallExecutor}; pub enum TestStatus { Pass, @@ -26,8 +26,12 @@ pub fn run_test( Ok(program) => { // Run the backend to ensure the PWG evaluates functions like std::hash::pedersen, // otherwise constraints involving these expressions will not error. - let circuit_execution = - execute_circuit(blackbox_solver, &program.circuit, WitnessMap::new(), show_output); + let circuit_execution = execute_circuit( + &program.circuit, + WitnessMap::new(), + blackbox_solver, + &mut DefaultForeignCallExecutor::new(show_output), + ); test_status_program_compile_pass(test_function, program.debug, circuit_execution) } Err(err) => test_status_program_compile_fail(err, test_function), diff --git a/tooling/nargo/src/package.rs b/tooling/nargo/src/package.rs index 16f65d329ba..94c7c5b9c98 100644 --- a/tooling/nargo/src/package.rs +++ b/tooling/nargo/src/package.rs @@ -43,6 +43,8 @@ impl Dependency { #[derive(Clone)] pub struct Package { + // A semver string which specifies the compiler version required to compile this package + pub compiler_required_version: Option, pub root_dir: PathBuf, pub package_type: PackageType, pub entry_path: PathBuf, diff --git a/tooling/nargo_cli/Cargo.toml b/tooling/nargo_cli/Cargo.toml index a1440dc2ecb..1a08514dc5f 100644 --- a/tooling/nargo_cli/Cargo.toml +++ b/tooling/nargo_cli/Cargo.toml @@ -15,7 +15,7 @@ path = "src/main.rs" [build-dependencies] rustc_version = "0.4.0" -build-data = "0.1.3" +build-data.workspace = true toml.workspace = true [dependencies] @@ -40,14 +40,9 @@ prettytable-rs = "0.10" rayon = "1.8.0" thiserror.workspace = true tower.workspace = true -async-lsp = { version = "0.0.5", default-features = false, features = [ - "client-monitor", - "stdio", - "tracing", - "tokio", -] } -const_format = "0.2.30" -hex = "0.4.2" +async-lsp = { workspace = true, features = ["client-monitor", "stdio", "tracing", "tokio"] } +const_format.workspace = true +hex.workspace = true termcolor = "1.1.2" color-eyre = "0.6.2" tokio = { version = "1.0", features = ["io-std"] } diff --git a/tooling/nargo_cli/build.rs b/tooling/nargo_cli/build.rs index c6682cff13e..0d1acca6ee9 100644 --- a/tooling/nargo_cli/build.rs +++ b/tooling/nargo_cli/build.rs @@ -6,8 +6,8 @@ use std::{env, fs}; fn check_rustc_version() { assert!( - version().unwrap() >= Version::parse("1.66.0").unwrap(), - "The minimal supported rustc version is 1.66.0." + version().unwrap() >= Version::parse("1.71.1").unwrap(), + "The minimal supported rustc version is 1.71.1." ); } diff --git a/tooling/nargo_cli/src/cli/check_cmd.rs b/tooling/nargo_cli/src/cli/check_cmd.rs index 30309f88f32..57b36b8932b 100644 --- a/tooling/nargo_cli/src/cli/check_cmd.rs +++ b/tooling/nargo_cli/src/cli/check_cmd.rs @@ -1,12 +1,14 @@ use crate::backends::Backend; -use crate::errors::{CliError, CompileError}; +use crate::errors::CliError; use clap::Args; use iter_extended::btree_map; -use nargo::{package::Package, prepare_package}; +use nargo::{errors::CompileError, package::Package, prepare_package}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::{AbiParameter, AbiType, MAIN_RETURN_NAME}; -use noirc_driver::{check_crate, compute_function_abi, CompileOptions}; +use noirc_driver::{ + check_crate, compute_function_abi, CompileOptions, NOIR_ARTIFACT_VERSION_STRING, +}; use noirc_frontend::{ graph::{CrateId, CrateName}, hir::Context, @@ -39,7 +41,11 @@ pub(crate) fn run( let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; let selection = args.package.map_or(default_selection, PackageSelection::Selected); - let workspace = resolve_workspace_from_toml(&toml_path, selection)?; + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; for package in &workspace { check_package(package, &args.compile_options)?; diff --git a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs index 856970544b8..59143526b24 100644 --- a/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs +++ b/tooling/nargo_cli/src/cli/codegen_verifier_cmd.rs @@ -13,7 +13,7 @@ use clap::Args; use nargo::package::Package; use nargo::workspace::Workspace; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::CompileOptions; +use noirc_driver::{CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::graph::CrateName; /// Generates a Solidity verifier smart contract for the program @@ -40,7 +40,11 @@ pub(crate) fn run( let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; let selection = args.package.map_or(default_selection, PackageSelection::Selected); - let workspace = resolve_workspace_from_toml(&toml_path, selection)?; + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; let (np_language, opcode_support) = backend.get_backend_info()?; for package in &workspace { diff --git a/tooling/nargo_cli/src/cli/compile_cmd.rs b/tooling/nargo_cli/src/cli/compile_cmd.rs index 039fee5dbc4..9ffbc26828e 100644 --- a/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -10,6 +10,7 @@ use nargo::artifacts::contract::PreprocessedContract; use nargo::artifacts::contract::PreprocessedContractFunction; use nargo::artifacts::debug::DebugArtifact; use nargo::artifacts::program::PreprocessedProgram; +use nargo::errors::CompileError; use nargo::package::Package; use nargo::prepare_package; use nargo::workspace::Workspace; @@ -21,7 +22,7 @@ use noirc_frontend::graph::CrateName; use clap::Args; use crate::backends::Backend; -use crate::errors::{CliError, CompileError}; +use crate::errors::CliError; use super::fs::program::{ read_debug_artifact_from_file, read_program_from_file, save_contract_to_file, @@ -61,7 +62,12 @@ pub(crate) fn run( let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; let selection = args.package.map_or(default_selection, PackageSelection::Selected); - let workspace = resolve_workspace_from_toml(&toml_path, selection)?; + + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_owned()), + )?; let circuit_dir = workspace.target_directory_path(); let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace @@ -188,6 +194,7 @@ fn compile_program( noir_version: preprocessed_program.noir_version, debug: debug_artifact.debug_symbols.remove(0), file_map: debug_artifact.file_map, + warnings: debug_artifact.warnings, }) } else { None @@ -261,8 +268,11 @@ fn save_program(program: CompiledProgram, package: &Package, circuit_dir: &Path) save_program_to_file(&preprocessed_program, &package.name, circuit_dir); - let debug_artifact = - DebugArtifact { debug_symbols: vec![program.debug], file_map: program.file_map }; + let debug_artifact = DebugArtifact { + debug_symbols: vec![program.debug], + file_map: program.file_map, + warnings: program.warnings, + }; let circuit_name: String = (&package.name).into(); save_debug_artifact_to_file(&debug_artifact, &circuit_name, circuit_dir); } @@ -275,6 +285,7 @@ fn save_contract(contract: CompiledContract, package: &Package, circuit_dir: &Pa let debug_artifact = DebugArtifact { debug_symbols: contract.functions.iter().map(|function| function.debug.clone()).collect(), file_map: contract.file_map, + warnings: contract.warnings, }; let preprocessed_functions = vecmap(contract.functions, |func| PreprocessedContractFunction { diff --git a/tooling/nargo_cli/src/cli/debug_cmd.rs b/tooling/nargo_cli/src/cli/debug_cmd.rs index 82cd3349ec4..1d344058312 100644 --- a/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -7,7 +7,7 @@ use nargo::package::Package; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::{Format, InputValue}; use noirc_abi::InputMap; -use noirc_driver::{CompileOptions, CompiledProgram}; +use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::graph::CrateName; use super::compile_cmd::compile_bin_package; @@ -41,7 +41,11 @@ pub(crate) fn run( ) -> Result<(), CliError> { let toml_path = get_package_manifest(&config.program_dir)?; let selection = args.package.map_or(PackageSelection::DefaultOrAll, PackageSelection::Selected); - let workspace = resolve_workspace_from_toml(&toml_path, selection)?; + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; let target_dir = &workspace.target_directory_path(); let (np_language, opcode_support) = backend.get_backend_info()?; @@ -112,6 +116,7 @@ pub(crate) fn debug_program( let debug_artifact = DebugArtifact { debug_symbols: vec![compiled_program.debug.clone()], file_map: compiled_program.file_map.clone(), + warnings: compiled_program.warnings.clone(), }; noir_debugger::debug_circuit( @@ -119,7 +124,6 @@ pub(crate) fn debug_program( &compiled_program.circuit, debug_artifact, initial_witness, - true, ) .map_err(CliError::from) } diff --git a/tooling/nargo_cli/src/cli/execute_cmd.rs b/tooling/nargo_cli/src/cli/execute_cmd.rs index 1819c9a6f06..91e4b800453 100644 --- a/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -4,11 +4,12 @@ use clap::Args; use nargo::artifacts::debug::DebugArtifact; use nargo::constants::PROVER_INPUT_FILE; use nargo::errors::try_to_diagnose_runtime_error; +use nargo::ops::DefaultForeignCallExecutor; use nargo::package::Package; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::{Format, InputValue}; use noirc_abi::InputMap; -use noirc_driver::{CompileOptions, CompiledProgram}; +use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::graph::CrateName; use super::compile_cmd::compile_bin_package; @@ -48,7 +49,11 @@ pub(crate) fn run( let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; let selection = args.package.map_or(default_selection, PackageSelection::Selected); - let workspace = resolve_workspace_from_toml(&toml_path, selection)?; + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; let target_dir = &workspace.target_directory_path(); let (np_language, opcode_support) = backend.get_backend_info()?; @@ -102,10 +107,10 @@ pub(crate) fn execute_program( let initial_witness = compiled_program.abi.encode(inputs_map, None)?; let solved_witness_err = nargo::ops::execute_circuit( - &blackbox_solver, &compiled_program.circuit, initial_witness, - true, + &blackbox_solver, + &mut DefaultForeignCallExecutor::new(true), ); match solved_witness_err { Ok(solved_witness) => Ok(solved_witness), @@ -113,6 +118,7 @@ pub(crate) fn execute_program( let debug_artifact = DebugArtifact { debug_symbols: vec![compiled_program.debug.clone()], file_map: compiled_program.file_map.clone(), + warnings: compiled_program.warnings.clone(), }; if let Some(diagnostic) = try_to_diagnose_runtime_error(&err, &compiled_program.debug) { diff --git a/tooling/nargo_cli/src/cli/fmt_cmd.rs b/tooling/nargo_cli/src/cli/fmt_cmd.rs index 31b45cc092a..eaa66fff02b 100644 --- a/tooling/nargo_cli/src/cli/fmt_cmd.rs +++ b/tooling/nargo_cli/src/cli/fmt_cmd.rs @@ -3,8 +3,9 @@ use std::{fs::DirEntry, path::Path}; use clap::Args; use fm::FileManager; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; use noirc_errors::CustomDiagnostic; -use noirc_frontend::hir::def_map::parse_file; +use noirc_frontend::{hir::def_map::parse_file, parser::ParserError}; use crate::errors::CliError; @@ -15,7 +16,11 @@ pub(crate) struct FormatCommand {} 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, PackageSelection::All)?; + let workspace = resolve_workspace_from_toml( + &toml_path, + PackageSelection::All, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; let config = nargo_fmt::Config::read(&config.program_dir) .map_err(|err| CliError::Generic(err.to_string()))?; @@ -28,7 +33,8 @@ pub(crate) fn run(_args: FormatCommand, config: NargoConfig) -> Result<(), CliEr let file_id = file_manager.add_file(&entry.path()).expect("file exists"); let (parsed_module, errors) = parse_file(&file_manager, file_id); - if !errors.is_empty() { + let is_all_warnings = errors.iter().all(ParserError::is_warning); + if !is_all_warnings { let errors = errors .into_iter() .map(|error| { diff --git a/tooling/nargo_cli/src/cli/info_cmd.rs b/tooling/nargo_cli/src/cli/info_cmd.rs index 50021e842c4..b1cd5f0b64f 100644 --- a/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/tooling/nargo_cli/src/cli/info_cmd.rs @@ -1,10 +1,15 @@ +use std::collections::HashMap; + use acvm::Language; use backend_interface::BackendError; use clap::Args; use iter_extended::vecmap; -use nargo::package::Package; +use nargo::{artifacts::debug::DebugArtifact, package::Package}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::{CompileOptions, CompiledContract, CompiledProgram}; +use noirc_driver::{ + CompileOptions, CompiledContract, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, +}; +use noirc_errors::{debug_info::OpCodesCount, Location}; use noirc_frontend::graph::CrateName; use prettytable::{row, table, Row}; use rayon::prelude::*; @@ -34,6 +39,9 @@ pub(crate) struct InfoCommand { #[clap(long, hide = true)] json: bool, + #[clap(long, hide = true)] + profile_info: bool, + #[clap(flatten)] compile_options: CompileOptions, } @@ -47,7 +55,11 @@ pub(crate) fn run( let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; let selection = args.package.map_or(default_selection, PackageSelection::Selected); - let workspace = resolve_workspace_from_toml(&toml_path, selection)?; + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace .into_iter() @@ -65,6 +77,23 @@ pub(crate) fn run( &args.compile_options, )?; + if args.profile_info { + for compiled_program in &compiled_programs { + let span_opcodes = compiled_program.debug.count_span_opcodes(); + let debug_artifact: DebugArtifact = compiled_program.clone().into(); + print_span_opcodes(span_opcodes, &debug_artifact); + } + + for compiled_contract in &compiled_contracts { + let debug_artifact: DebugArtifact = compiled_contract.clone().into(); + let functions = &compiled_contract.functions; + for contract_function in functions { + let span_opcodes = contract_function.debug.count_span_opcodes(); + print_span_opcodes(span_opcodes, &debug_artifact); + } + } + } + let program_info = binary_packages .into_par_iter() .zip(compiled_programs) @@ -115,6 +144,55 @@ pub(crate) fn run( Ok(()) } +/// Provides profiling information on +/// +/// Number of OpCodes in relation to Noir source file +/// and line number information +fn print_span_opcodes( + span_opcodes_map: HashMap, + debug_artifact: &DebugArtifact, +) { + let mut pairs: Vec<(&Location, &OpCodesCount)> = span_opcodes_map.iter().collect(); + + pairs.sort_by(|a, b| { + a.1.acir_size.cmp(&b.1.acir_size).then_with(|| a.1.brillig_size.cmp(&b.1.brillig_size)) + }); + + for (location, opcodes_count) in pairs { + let debug_file = debug_artifact.file_map.get(&location.file).unwrap(); + + let start_byte = byte_index(&debug_file.source, location.span.start() + 1); + let end_byte = byte_index(&debug_file.source, location.span.end() + 1); + let range = start_byte..end_byte; + let span_content = &debug_file.source[range]; + let line = debug_artifact.location_line_index(*location).unwrap() + 1; + println!( + "Ln. {}: {} (ACIR:{}, Brillig:{} opcode|s) in file: {}", + line, + span_content, + opcodes_count.acir_size, + opcodes_count.brillig_size, + debug_file.path.to_str().unwrap() + ); + } +} +fn byte_index(string: &str, index: u32) -> usize { + let mut byte_index = 0; + let mut char_index = 0; + + #[allow(clippy::explicit_counter_loop)] + for (byte_offset, _) in string.char_indices() { + if char_index == index { + return byte_index; + } + + byte_index = byte_offset; + char_index += 1; + } + + byte_index +} + #[derive(Debug, Default, Serialize)] struct InfoReport { programs: Vec, diff --git a/tooling/nargo_cli/src/cli/init_cmd.rs b/tooling/nargo_cli/src/cli/init_cmd.rs index 9d7700a6598..e53c2e4cdc9 100644 --- a/tooling/nargo_cli/src/cli/init_cmd.rs +++ b/tooling/nargo_cli/src/cli/init_cmd.rs @@ -73,7 +73,7 @@ pub(crate) fn initialize_project( name = "{package_name}" type = "{package_type}" authors = [""] -compiler_version = "{NOIRC_VERSION}" +compiler_version = ">={NOIRC_VERSION}" [dependencies]"# ); diff --git a/tooling/nargo_cli/src/cli/prove_cmd.rs b/tooling/nargo_cli/src/cli/prove_cmd.rs index af300b7ebe0..3586e73ff2e 100644 --- a/tooling/nargo_cli/src/cli/prove_cmd.rs +++ b/tooling/nargo_cli/src/cli/prove_cmd.rs @@ -4,7 +4,7 @@ use nargo::package::Package; use nargo::workspace::Workspace; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::Format; -use noirc_driver::{CompileOptions, CompiledProgram}; +use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::graph::CrateName; use super::compile_cmd::compile_bin_package; @@ -51,7 +51,11 @@ pub(crate) fn run( let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; let selection = args.package.map_or(default_selection, PackageSelection::Selected); - let workspace = resolve_workspace_from_toml(&toml_path, selection)?; + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; let (np_language, opcode_support) = backend.get_backend_info()?; for package in &workspace { diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs index 4ba2fc35766..e117d8555a5 100644 --- a/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -8,7 +8,7 @@ use nargo::{ prepare_package, }; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; -use noirc_driver::CompileOptions; +use noirc_driver::{CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::{graph::CrateName, hir::FunctionNameMatch}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; @@ -51,7 +51,11 @@ pub(crate) fn run( let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; let selection = args.package.map_or(default_selection, PackageSelection::Selected); - let workspace = resolve_workspace_from_toml(&toml_path, selection)?; + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; let pattern = match &args.test_name { Some(name) => { diff --git a/tooling/nargo_cli/src/cli/verify_cmd.rs b/tooling/nargo_cli/src/cli/verify_cmd.rs index 6ae2b78fd0c..8c6d92b3d2f 100644 --- a/tooling/nargo_cli/src/cli/verify_cmd.rs +++ b/tooling/nargo_cli/src/cli/verify_cmd.rs @@ -11,7 +11,7 @@ use nargo::package::Package; use nargo::workspace::Workspace; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::Format; -use noirc_driver::{CompileOptions, CompiledProgram}; +use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::graph::CrateName; /// Given a proof and a program, verify whether the proof is valid @@ -42,7 +42,11 @@ pub(crate) fn run( let default_selection = if args.workspace { PackageSelection::All } else { PackageSelection::DefaultOrAll }; let selection = args.package.map_or(default_selection, PackageSelection::Selected); - let workspace = resolve_workspace_from_toml(&toml_path, selection)?; + let workspace = resolve_workspace_from_toml( + &toml_path, + selection, + Some(NOIR_ARTIFACT_VERSION_STRING.to_string()), + )?; let (np_language, opcode_support) = backend.get_backend_info()?; for package in &workspace { diff --git a/tooling/nargo_cli/src/errors.rs b/tooling/nargo_cli/src/errors.rs index b73a7888f32..92da74c71d4 100644 --- a/tooling/nargo_cli/src/errors.rs +++ b/tooling/nargo_cli/src/errors.rs @@ -1,10 +1,8 @@ use acvm::acir::native_types::WitnessMapError; use hex::FromHexError; -use nargo::NargoError; +use nargo::{errors::CompileError, NargoError}; use nargo_toml::ManifestError; use noirc_abi::errors::{AbiError, InputParserError}; -use noirc_errors::reporter::ReportedErrors; -use noirc_frontend::graph::CrateName; use std::path::PathBuf; use thiserror::Error; @@ -87,24 +85,3 @@ pub(crate) enum BackendError { #[error("Backend installation failed: {0}")] InstallationError(#[from] std::io::Error), } - -/// Errors covering situations where a package cannot be compiled. -#[derive(Debug, Error)] -pub(crate) enum CompileError { - #[error("Package `{0}` has type `lib` but only `bin` types can be compiled")] - LibraryCrate(CrateName), - - #[error("Package `{0}` is expected to have a `main` function but it does not")] - MissingMainFunction(CrateName), - - /// Errors encountered while compiling the Noir program. - /// These errors are already written to stderr. - #[error("Aborting due to {} previous error{}", .0.error_count, if .0.error_count == 1 { "" } else { "s" })] - ReportedErrors(ReportedErrors), -} - -impl From for CompileError { - fn from(errors: ReportedErrors) -> Self { - Self::ReportedErrors(errors) - } -} 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 index 1c28b75f74e..7572c9ac2cf 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/1_mul/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/1_mul/target/acir.gz 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 index f01447653fa..76f5c8a2fe2 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/1_mul/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/1_mul/target/witness.gz 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 index 37012dece4e..46405fc2029 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/2_div/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/2_div/target/acir.gz 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 index d8733d8606e..3145b77d957 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/2_div/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/2_div/target/witness.gz 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 index 490b5f41330..42e66d90f73 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/3_add/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/3_add/target/acir.gz 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 index f44e09476bc..0cfc48c525e 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/3_add/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/3_add/target/witness.gz 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 index f25a320b01e..787db190b49 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/6_array/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/6_array/target/acir.gz 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 index 6aba7ca03c0..cc96fd18e00 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/6_array/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/6_array/target/witness.gz 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 index 8b417c250a3..5ddc1ba38e6 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/7_function/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/7_function/target/acir.gz 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 index 9dcb6d30140..0bb522d210e 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/7_function/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/7_function/target/witness.gz 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 index ba3c09529b1..bb735d852d5 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/acir.gz 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 index 3cacd507613..b80b33eecdf 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/witness.gz 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 index 647dc586b04..4756ea6b632 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/acir.gz 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 index 13d2ec1b7b5..890e987dd74 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/witness.gz 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 index 7a59062156f..45c1cc44c8e 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/acir.gz 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 index 28357d49cd1..bdc4e70ba09 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/witness.gz 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 index b7a2d88a36e..69cbde31d9d 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_acir_as_brillig/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_acir_as_brillig/target/acir.gz 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 index 96855675d25..844178f0430 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_acir_as_brillig/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_acir_as_brillig/target/witness.gz 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 index b91295d3cec..b69e231774b 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_calls/target/acir.gz 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 index 96855675d25..844178f0430 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_calls/target/witness.gz 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 index 1d348538bff..59b89c22bc3 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_array/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_calls_array/target/acir.gz 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 index e8bede3cbed..d1819212993 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_fns_as_values/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_fns_as_values/target/acir.gz 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 index 0b563e5b0be..f4a9c9f6dda 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_fns_as_values/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_fns_as_values/target/witness.gz 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 index 06569c728ad..73c742a2dd1 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_hash_to_field/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_hash_to_field/target/acir.gz 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 index 4c41f9a8bb1..1529254d597 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_hash_to_field/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_hash_to_field/target/witness.gz 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 index 3ebdee29a46..db158f61882 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_oracle/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_oracle/target/acir.gz 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 index b8eaf5a13a0..27f6f353d25 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_pedersen/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_pedersen/target/acir.gz 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 index 4853adb029b..c0c91d81546 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_recursion/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_recursion/target/acir.gz 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 index 4ab33919248..ac18684a07e 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_unitialised_arrays/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_unitialised_arrays/target/acir.gz 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 index 869536a1d98..ceaf7ad008e 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_unitialised_arrays/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_unitialised_arrays/target/witness.gz 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 index 7380f30d354..46a738a97e3 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/acir.gz 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 index 2ff44d73044..5bafffff0d8 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/witness.gz 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 index 01de08c56d2..51e30b8bbc1 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_661/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_661/target/acir.gz 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 index ad901ffb80d..2683a9ba4ae 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_661/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_661/target/witness.gz 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 new file mode 100644 index 00000000000..6d43d0374b9 Binary files /dev/null and b/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_underflow/target/acir.gz 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 new file mode 100644 index 00000000000..5b2d3b80af5 Binary files /dev/null and b/tooling/nargo_cli/tests/acir_artifacts/conditional_regression_underflow/target/witness.gz 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 index 275afa4c6e0..b8577dbd3ac 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/acir.gz 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 index f87a868de3d..7c125021d96 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/witness.gz 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 index c2c8c9f9469..9be98aef491 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/hash_to_field/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/hash_to_field/target/acir.gz 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 index 6802e590420..743d797096b 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/hash_to_field/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/hash_to_field/target/witness.gz 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 index 889352e685f..75b1cbb5072 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/acir.gz 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 index c4ded4eea08..6351d29dd11 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/witness.gz 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 index e78bf59102d..9f518522755 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/acir.gz 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 index d2ff2ed1b94..62a1378dece 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/witness.gz 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 index fcfd2ab066d..3db0a495a9d 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/acir.gz 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 index ba1f5565170..9c9e80efe8f 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/witness.gz 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 index ed80135203d..f92aa2603b4 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/regression/target/acir.gz 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 index 76afd0975f6..dc1f8e0e3f7 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/regression/target/witness.gz 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 index bb54dc5f548..5c0339446c5 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/acir.gz 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 index e8653567d5f..095aef252ee 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/witness.gz 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 index 4005c95b18d..047e59422ee 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/acir.gz 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 index 91324bd7284..91bf1aeb7ad 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/sha2_blocks/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/sha2_blocks/target/acir.gz deleted file mode 100644 index 1e9c237d083..00000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/sha2_blocks/target/acir.gz and /dev/null differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/sha2_blocks/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/sha2_blocks/target/witness.gz deleted file mode 100644 index 6bedf3922b0..00000000000 Binary files a/tooling/nargo_cli/tests/acir_artifacts/sha2_blocks/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 index 881bf967590..512a9089ac9 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/acir.gz 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 index 746c6fc56a2..9450bf170ec 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/witness.gz 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 index 505e8f56bb9..82747c17417 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/acir.gz 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 index c180c733428..6627fd7d53f 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/witness.gz 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 index 906e4f2010b..39a17a5a529 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/acir.gz 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 index c56799e636a..a35e3011ee6 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/witness.gz 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 index 25a54000fdb..84fc5cc5de2 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_bitwise/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_bitwise/target/acir.gz 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 index 2cb925c0149..2afa317a120 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_bitwise/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_bitwise/target/witness.gz 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 index 80a70ba7ee3..8c5fd3c0bd4 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/acir.gz 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 index e730d65c475..4b051d62ee2 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/witness.gz 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 index 9a9f3a76992..1916c475919 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/acir.gz 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 index 0bc6d3e8fbc..171330f5142 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/witness.gz 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 index 19d240987a8..6bbdaef4a9b 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_shift_left_right/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_shift_left_right/target/acir.gz 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 index 9c05da63d6b..6f15adc6525 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_shift_left_right/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_shift_left_right/target/witness.gz 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 index 30b5d36a2e3..7b605a2b87b 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/acir.gz 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 index 1cbd7129bb0..148355f9335 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/witness.gz 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 new file mode 100644 index 00000000000..6b1f189a331 Binary files /dev/null and b/tooling/nargo_cli/tests/acir_artifacts/slice_struct_field/target/acir.gz 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 new file mode 100644 index 00000000000..f404e58ade3 Binary files /dev/null and b/tooling/nargo_cli/tests/acir_artifacts/slice_struct_field/target/witness.gz 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 index 70a32bccf6f..7a053fcb196 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slices/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/slices/target/acir.gz 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 index ac4ffe17323..359b2f75601 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slices/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/slices/target/witness.gz 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 index 26528ac0100..424f4bd2d0f 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/strings/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/strings/target/acir.gz 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 index aec6f367127..df6294bc970 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/acir.gz 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 index 88ed370f861..b2ac9601bae 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/witness.gz 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 index c505c205faa..2371186e8fc 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/acir.gz 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 index 5f82918d57a..610802628c6 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/witness.gz 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 index 247509bd50a..4deef489b9c 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/acir.gz 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 index a672966388a..71d29209eba 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/witness.gz 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 index 14286c04ef9..02d2bd105f1 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/acir.gz 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 index 44c71164ae4..610802628c6 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/compile_failure/assert_constant_fail/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/assert_constant_fail/Nargo.toml index a8c9b4ad344..2eaf67246e1 100644 --- a/tooling/nargo_cli/tests/compile_failure/assert_constant_fail/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/assert_constant_fail/Nargo.toml @@ -2,6 +2,4 @@ name = "assert_constant_fail" type = "bin" authors = [""] -compiler_version = "0.9.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/assert_eq_struct/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/assert_eq_struct/Nargo.toml index 055c23234ce..9fcdcc10bb7 100644 --- a/tooling/nargo_cli/tests/compile_failure/assert_eq_struct/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/assert_eq_struct/Nargo.toml @@ -2,6 +2,4 @@ name = "assert_eq_struct" type = "bin" authors = [""] -compiler_version = "0.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_failure/assert_eq_struct/src/main.nr b/tooling/nargo_cli/tests/compile_failure/assert_eq_struct/src/main.nr index c2eac091733..54b937e5f1d 100644 --- a/tooling/nargo_cli/tests/compile_failure/assert_eq_struct/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/assert_eq_struct/src/main.nr @@ -1,6 +1,5 @@ struct myStruct {} - // `assert_eq` should not allow asserting equality between types for which `==` is not defined. -fn main(x : myStruct, y : pub myStruct) { +fn main(x: myStruct, y: pub myStruct) { assert_eq(x, y); } diff --git a/tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/Nargo.toml index 181af302d8f..7ce776e5ce6 100644 --- a/tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_assert_fail" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/src/main.nr b/tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/src/main.nr index 801a818c816..da9d4ec1ac8 100644 --- a/tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/brillig_assert_fail/src/main.nr @@ -1,11 +1,11 @@ // Tests a very simple program. // // The features being tested is using assert on brillig -fn main(x: Field) { +fn main(x: Field) { assert(1 == conditional(x as bool)); } -unconstrained fn conditional(x : bool) -> Field { +unconstrained fn conditional(x: bool) -> Field { assert(x); 1 } diff --git a/tooling/nargo_cli/tests/compile_failure/constrain_typo/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/constrain_typo/Nargo.toml index db1c3480387..191121e59b7 100644 --- a/tooling/nargo_cli/tests/compile_failure/constrain_typo/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/constrain_typo/Nargo.toml @@ -2,6 +2,5 @@ name = "constrain_typo" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_failure/custom_entry_not_found/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/custom_entry_not_found/Nargo.toml index 0ccb94aff1a..a32696d3370 100644 --- a/tooling/nargo_cli/tests/compile_failure/custom_entry_not_found/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/custom_entry_not_found/Nargo.toml @@ -4,6 +4,5 @@ type = "bin" # Testing that this file is missing and doesn't fallback to default `main.nr` file entry = "src/foobarbaz.nr" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/Nargo.toml index 6a49afec2c4..afe5a5134ca 100644 --- a/tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/Nargo.toml @@ -2,7 +2,5 @@ name = "dep_impl_primitive" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] bad_impl = { path = "../../test_libraries/bad_impl" } diff --git a/tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/src/main.nr b/tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/src/main.nr index ff9a40da18e..e61ae82b62c 100644 --- a/tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/dep_impl_primitive/src/main.nr @@ -1,5 +1,5 @@ use dep::bad_impl; -fn main(x : Field) { +fn main(x: Field) { x.something(); } diff --git a/tooling/nargo_cli/tests/compile_failure/depend_on_bin/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/depend_on_bin/Nargo.toml index 2404e68e180..8334a38eb4b 100644 --- a/tooling/nargo_cli/tests/compile_failure/depend_on_bin/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/depend_on_bin/Nargo.toml @@ -2,7 +2,5 @@ name = "depend_on_bin" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] bin_dep = { path = "../../test_libraries/bin_dep" } diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/Nargo.toml index 55e36368845..aad13c7d97f 100644 --- a/tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/Nargo.toml @@ -2,6 +2,5 @@ name = "divide_by_zero" type = "bin" authors = [""] -compiler_version = "0.10.3" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/src/main.nr b/tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/src/main.nr index 2259d51e6de..58adc5444b1 100644 --- a/tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/div_by_zero_constants/src/main.nr @@ -3,4 +3,4 @@ use dep::std; fn main() { let a: Field = 3 / 0; std::println(a); -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/Nargo.toml index d3b69d8c41b..22ff18075cd 100644 --- a/tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/Nargo.toml @@ -2,6 +2,5 @@ name = "div_by_zero_modulo" type = "bin" authors = [""] -compiler_version = "0.10.5" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/src/main.nr b/tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/src/main.nr index f20c39486e0..d938ab7fca8 100644 --- a/tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/div_by_zero_modulo/src/main.nr @@ -1,7 +1,7 @@ fn main() { let a: u32 = 6; - let b = 3; - let c = 0; - let res = (a*b) % c; - assert(res != 5); -} \ No newline at end of file + let b = 3; + let c = 0; + let res = (a * b) % c; + assert(res != 5); +} diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_numerator_witness/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/div_by_zero_numerator_witness/Nargo.toml index 58a60a38a0c..30a7eb62645 100644 --- a/tooling/nargo_cli/tests/compile_failure/div_by_zero_numerator_witness/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/div_by_zero_numerator_witness/Nargo.toml @@ -2,6 +2,5 @@ name = "div_by_zero_numerator_witness" type = "bin" authors = [""] -compiler_version = "0.10.3" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/Nargo.toml index 08dbe74f018..e4968f6182d 100644 --- a/tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/Nargo.toml @@ -2,6 +2,5 @@ name = "div_by_zero_witness" type = "bin" authors = [""] -compiler_version = "0.10.3" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/src/main.nr b/tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/src/main.nr index 4ce567e49a6..a814f88f320 100644 --- a/tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/div_by_zero_witness/src/main.nr @@ -1,7 +1,6 @@ use dep::std; - // It is expected that `y` must be equal to 0. -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { let a: Field = x / y; std::println(a); } diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/Nargo.toml index 7c2c50884fe..18352cb34b5 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/Nargo.toml @@ -2,6 +2,5 @@ name = "dup_trait_implementation_4" type = "bin" authors = [""] -compiler_version = "0.11.1" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/main.nr b/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/main.nr index b9f712ceff0..e03fe8b3eeb 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/main.nr @@ -2,5 +2,4 @@ mod module1; mod module2; mod module3; -fn main() { -} +fn main() {} diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/module3.nr b/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/module3.nr index a7612345cf1..17874893190 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/module3.nr +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_4/src/module3.nr @@ -1,6 +1,5 @@ use crate::module1::MyTrait; use crate::module2::MyStruct; - // those are not the same 'Path', but they refer to the same trait & impl // so a Duplicate error should be thrown impl MyTrait for MyStruct {} diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/Nargo.toml index b5bacc433f3..40b7c3d0269 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/Nargo.toml @@ -2,6 +2,5 @@ name = "dup_trait_implementation_5" type = "bin" authors = [""] -compiler_version = "0.11.1" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/main.nr b/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/main.nr index 78e3867e4a1..b5719009898 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_implementation_5/src/main.nr @@ -3,5 +3,4 @@ mod module2; mod module3; mod module4; -fn main() { -} +fn main() {} diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/Nargo.toml index d8b44af47c2..078a336c282 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/Nargo.toml @@ -2,6 +2,4 @@ name = "dup_trait_items_1" type = "bin" authors = [""] -compiler_version = "0.15.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/src/main.nr b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/src/main.nr index 9055d6e3998..863139333f7 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_1/src/main.nr @@ -3,5 +3,4 @@ trait MyTrait { fn SomeFunc(); } -fn main() { -} +fn main() {} diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/Nargo.toml index b37256a1292..41e1a3b3fd9 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/Nargo.toml @@ -2,6 +2,4 @@ name = "dup_trait_items_2" type = "bin" authors = [""] -compiler_version = "0.15.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/src/main.nr b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/src/main.nr index 312b1e5a9d4..cdcac745208 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_2/src/main.nr @@ -3,5 +3,4 @@ trait MyTrait { let SomeConst: Field; } -fn main() { -} +fn main() {} diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/Nargo.toml index c9a0de11174..1388f3c83ee 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/Nargo.toml @@ -2,6 +2,4 @@ name = "dup_trait_items_3" type = "bin" authors = [""] -compiler_version = "0.15.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/src/main.nr b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/src/main.nr index ca97a9a143d..f6ed35468b9 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_3/src/main.nr @@ -3,5 +3,4 @@ trait MyTrait { type SomeType; } -fn main() { -} +fn main() {} diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/Nargo.toml index 5e4af3a29ae..43e8096548b 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/Nargo.toml @@ -2,6 +2,4 @@ name = "dup_trait_items_4" type = "bin" authors = [""] -compiler_version = "0.15.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/src/main.nr b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/src/main.nr index da0532e39c1..fc0a7011a5d 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_4/src/main.nr @@ -3,5 +3,4 @@ trait MyTrait { fn MyItem(); } -fn main() { -} +fn main() {} diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/Nargo.toml index 2d8c9aad7ec..0af8ef88cea 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/Nargo.toml @@ -2,6 +2,4 @@ name = "dup_trait_items_5" type = "bin" authors = [""] -compiler_version = "0.15.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/src/main.nr b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/src/main.nr index 4881a338a84..da42d27ac36 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_5/src/main.nr @@ -3,5 +3,4 @@ trait MyTrait { let MyItem: u32; } -fn main() { -} +fn main() {} diff --git a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_6/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_6/Nargo.toml index 5107c10b41d..dd5f13438ec 100644 --- a/tooling/nargo_cli/tests/compile_failure/dup_trait_items_6/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/dup_trait_items_6/Nargo.toml @@ -2,6 +2,4 @@ name = "dup_trait_items_6" type = "bin" authors = [""] -compiler_version = "0.15.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/duplicate_declaration/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/duplicate_declaration/Nargo.toml index 56f65941b52..a4c82c70642 100644 --- a/tooling/nargo_cli/tests/compile_failure/duplicate_declaration/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/duplicate_declaration/Nargo.toml @@ -2,6 +2,5 @@ name = "duplicate_declaration" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_failure/duplicate_declaration/src/main.nr b/tooling/nargo_cli/tests/compile_failure/duplicate_declaration/src/main.nr index 09337e51c93..e4433ef4078 100644 --- a/tooling/nargo_cli/tests/compile_failure/duplicate_declaration/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/duplicate_declaration/src/main.nr @@ -1,8 +1,8 @@ // Duplicate functions should not compile -fn hello(x : Field) -> Field { +fn hello(x: Field) -> Field { x } -fn hello(x : Field) -> Field { +fn hello(x: Field) -> Field { x -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/Nargo.toml index 52a547e8d7b..7f1c2c097a4 100644 --- a/tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/Nargo.toml @@ -2,6 +2,5 @@ name = "dyn_index_fail_nested_array" type = "bin" authors = [""] -compiler_version = "0.11.1" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/src/main.nr b/tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/src/main.nr index e26625457d9..954d2e77c6e 100644 --- a/tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/dyn_index_fail_nested_array/src/main.nr @@ -3,6 +3,6 @@ struct Foo { b: Field, } -fn main(mut x : [Foo; 3], y : pub Field) { +fn main(mut x: [Foo; 3], y: pub Field) { assert(x[y + 2].a == 5); -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/Nargo.toml index c68615052c1..2c44a5356c3 100644 --- a/tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/Nargo.toml @@ -2,6 +2,5 @@ name = "dynamic_index_failure" type = "bin" authors = [""] -compiler_version = "0.10.3" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/src/main.nr b/tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/src/main.nr index 2665356ccd6..0af5f90eea6 100644 --- a/tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/dynamic_index_failure/src/main.nr @@ -1,11 +1,9 @@ fn main(mut x: [u32; 5], z: Field) { let idx = z + 10; - - x[z] = 4; + x[z] = 4; // Dynamic index is greater than length of the array assert(x[idx] != 0); - // TODO(#2133): Provide more accurate call stacks for arrays merged in if statements // if z != 20 { // x[0] = x[4]; @@ -20,4 +18,4 @@ fn main(mut x: [u32; 5], z: Field) { // } // } // assert(x[idx] != 0); -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/compile_failure/field_modulo/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/field_modulo/Nargo.toml index f6bc2dd70e2..94934f13e56 100644 --- a/tooling/nargo_cli/tests/compile_failure/field_modulo/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/field_modulo/Nargo.toml @@ -2,6 +2,4 @@ name = "field_modulo" type = "bin" authors = [""] -compiler_version = "0.9.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/field_modulo/src/main.nr b/tooling/nargo_cli/tests/compile_failure/field_modulo/src/main.nr index b27ba0892b3..a482b68806b 100644 --- a/tooling/nargo_cli/tests/compile_failure/field_modulo/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/field_modulo/src/main.nr @@ -1,4 +1,3 @@ - fn main(x: Field) -> pub Field { x % 2 } diff --git a/tooling/nargo_cli/tests/compile_failure/integer_literal_overflow/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/integer_literal_overflow/Nargo.toml index f29ec0408ea..ed607023878 100644 --- a/tooling/nargo_cli/tests/compile_failure/integer_literal_overflow/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/integer_literal_overflow/Nargo.toml @@ -2,6 +2,4 @@ name = "integer_literal_overflow" type = "bin" authors = [""] -compiler_version = "0.16.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/integer_literal_overflow/src/main.nr b/tooling/nargo_cli/tests/compile_failure/integer_literal_overflow/src/main.nr index ab1cb457fee..d89505c0085 100644 --- a/tooling/nargo_cli/tests/compile_failure/integer_literal_overflow/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/integer_literal_overflow/src/main.nr @@ -1,4 +1,3 @@ - fn main() { foo(1234) } diff --git a/tooling/nargo_cli/tests/compile_failure/invalid_dependency_name/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/invalid_dependency_name/Nargo.toml index 69b56a2e7d0..99d184acdcf 100644 --- a/tooling/nargo_cli/tests/compile_failure/invalid_dependency_name/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/invalid_dependency_name/Nargo.toml @@ -2,7 +2,5 @@ name = "invalid_dependency_name" type = "bin" authors = [""] -compiler_version = "0.9.0" - [dependencies] bad_name = { path = "../../test_libraries/bad_name" } diff --git a/tooling/nargo_cli/tests/compile_failure/multiple_contracts/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/multiple_contracts/Nargo.toml index c71c86c664b..d6e4e632f95 100644 --- a/tooling/nargo_cli/tests/compile_failure/multiple_contracts/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/multiple_contracts/Nargo.toml @@ -2,6 +2,4 @@ name = "multiple_contracts" type = "contract" authors = [""] -compiler_version = "0.9.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_failure/multiple_contracts/src/main.nr b/tooling/nargo_cli/tests/compile_failure/multiple_contracts/src/main.nr index 0562ca9ccd5..a6c49d75378 100644 --- a/tooling/nargo_cli/tests/compile_failure/multiple_contracts/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/multiple_contracts/src/main.nr @@ -1,4 +1,3 @@ contract Foo {} - contract Bar {} diff --git a/tooling/nargo_cli/tests/compile_failure/multiple_primary_attributes_fail/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/multiple_primary_attributes_fail/Nargo.toml index 7e699d4bbe0..9aa843d16dc 100644 --- a/tooling/nargo_cli/tests/compile_failure/multiple_primary_attributes_fail/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/multiple_primary_attributes_fail/Nargo.toml @@ -2,6 +2,4 @@ name = "multiple_primary_attributes_fail" type = "bin" authors = [""] -compiler_version = "0.9.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/mutability_regression_2911/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/mutability_regression_2911/Nargo.toml index 5136fad35ce..05db8252f3b 100644 --- a/tooling/nargo_cli/tests/compile_failure/mutability_regression_2911/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/mutability_regression_2911/Nargo.toml @@ -2,6 +2,4 @@ name = "mutability_regression_2911" type = "bin" authors = [""] -compiler_version = "0.9.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/sha2_blocks/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/no_impl_from_function/Nargo.toml similarity index 54% rename from tooling/nargo_cli/tests/execution_success/sha2_blocks/Nargo.toml rename to tooling/nargo_cli/tests/compile_failure/no_impl_from_function/Nargo.toml index 9aa46c465e9..0d243d0029d 100644 --- a/tooling/nargo_cli/tests/execution_success/sha2_blocks/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/no_impl_from_function/Nargo.toml @@ -1,7 +1,6 @@ [package] -name = "sha2_blocks" +name = "no_impl_from_function" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_failure/no_impl_from_function/src/main.nr b/tooling/nargo_cli/tests/compile_failure/no_impl_from_function/src/main.nr new file mode 100644 index 00000000000..b0c485c2bf5 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_failure/no_impl_from_function/src/main.nr @@ -0,0 +1,26 @@ +fn main() { + let array: [Field; 3] = [1, 2, 3]; + assert(foo(array)); + + // Ensure this still works if we have to infer the type of the integer literals + let array = [1, 2, 3]; + assert(foo(array)); +} + +fn foo(x: T) -> bool where T: Eq { + x.eq(x) +} + +trait Eq { + fn eq(self, other: Self) -> bool; +} + +impl Eq for [T; N] where T: Eq { + fn eq(self, other: Self) -> bool { + let mut ret = true; + for i in 0 .. self.len() { + ret &= self[i].eq(other[i]); + } + ret + } +} diff --git a/tooling/nargo_cli/tests/compile_failure/no_nested_impl/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/no_nested_impl/Nargo.toml new file mode 100644 index 00000000000..5179c0f6a5c --- /dev/null +++ b/tooling/nargo_cli/tests/compile_failure/no_nested_impl/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "no_nested_impl" +type = "bin" +authors = [""] +compiler_version = ">=0.18.0" + +[dependencies] \ No newline at end of file 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 new file mode 100644 index 00000000000..916567a7c04 --- /dev/null +++ b/tooling/nargo_cli/tests/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.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/orphaned_trait_impl/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/Nargo.toml index 47df960cc33..89f30bb1ba5 100644 --- a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/Nargo.toml @@ -2,8 +2,6 @@ name = "orphaned_trait_impl" type = "bin" authors = [""] -compiler_version = "0.12.0" - [dependencies] crate1 = { path = "crate1" } crate2 = { path = "crate2" } diff --git a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate1/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate1/Nargo.toml index b28e0e840c4..de1eddf2cf0 100644 --- a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate1/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate1/Nargo.toml @@ -2,6 +2,4 @@ name = "crate1" type = "lib" authors = [""] -compiler_version = "0.12.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate2/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate2/Nargo.toml index a90a5dcceea..c86c5edf51a 100644 --- a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate2/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/crate2/Nargo.toml @@ -2,6 +2,4 @@ name = "crate2" type = "lib" authors = [""] -compiler_version = "0.12.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/src/main.nr b/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/src/main.nr index d245bd68ea1..dfd88d8f074 100644 --- a/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/orphaned_trait_impl/src/main.nr @@ -1,6 +1,6 @@ impl dep::crate1::MyTrait for dep::crate2::MyStruct { } -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { assert(x != y); } diff --git a/tooling/nargo_cli/tests/compile_failure/overflowing_assignment/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/overflowing_assignment/Nargo.toml index 25bdea70129..612e3e7aaf6 100644 --- a/tooling/nargo_cli/tests/compile_failure/overflowing_assignment/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/overflowing_assignment/Nargo.toml @@ -2,6 +2,4 @@ name = "overflowing_assignment" type = "bin" authors = [""] -compiler_version = "0.9.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/overflowing_assignment/src/main.nr b/tooling/nargo_cli/tests/compile_failure/overflowing_assignment/src/main.nr index 78535a853a6..6b529103ca3 100644 --- a/tooling/nargo_cli/tests/compile_failure/overflowing_assignment/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/overflowing_assignment/src/main.nr @@ -1,5 +1,5 @@ fn main() { let x:u8 = -1; let y:u8 = 300; - assert(x!=y); + assert(x != y); } diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_self/trait_self/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/overlapping_generic_impls/Nargo.toml similarity index 51% rename from tooling/nargo_cli/tests/compile_success_empty/trait_self/trait_self/Nargo.toml rename to tooling/nargo_cli/tests/compile_failure/overlapping_generic_impls/Nargo.toml index 0dfaea44862..a279bfb053a 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_self/trait_self/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/overlapping_generic_impls/Nargo.toml @@ -1,7 +1,5 @@ [package] -name = "trait_self" +name = "overlapping_generic_impls" type = "bin" authors = [""] -compiler_version = "0.10.5" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/overlapping_generic_impls/src/main.nr b/tooling/nargo_cli/tests/compile_failure/overlapping_generic_impls/src/main.nr new file mode 100644 index 00000000000..95e4d53bf93 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_failure/overlapping_generic_impls/src/main.nr @@ -0,0 +1,6 @@ +trait Trait { fn t(self); } + +impl Trait for T { fn t(self){} } +impl Trait for u32 { fn t(self){} } + +fn main() {} diff --git a/tooling/nargo_cli/tests/compile_failure/package_name_empty/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/package_name_empty/Nargo.toml index 7c4dbd0c994..88382674780 100644 --- a/tooling/nargo_cli/tests/compile_failure/package_name_empty/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/package_name_empty/Nargo.toml @@ -2,6 +2,4 @@ name = "" type = "bin" authors = [""] -compiler_version = "0.9.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_failure/package_name_hyphen/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/package_name_hyphen/Nargo.toml index f8d0a85db4a..4882b83b8bf 100644 --- a/tooling/nargo_cli/tests/compile_failure/package_name_hyphen/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/package_name_hyphen/Nargo.toml @@ -2,6 +2,4 @@ name = "hyphenated-name" type = "bin" authors = [""] -compiler_version = "0.9.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml index 872c8f2030d..7c5e7f70774 100644 --- a/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/primary_attribute_struct/Nargo.toml @@ -3,6 +3,5 @@ name = "primary_attribute_struct" type = "bin" authors = [""] -compiler_version = "0.11.1" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/Nargo.toml index b8b1a2417dc..349698cc32d 100644 --- a/tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/Nargo.toml @@ -2,6 +2,5 @@ name = "radix_non_constant_length" type = "bin" authors = [""] -compiler_version = "0.10.2" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/src/main.nr b/tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/src/main.nr index adfbd265a1d..c6dd68d925c 100644 --- a/tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/radix_non_constant_length/src/main.nr @@ -1,4 +1,4 @@ -fn main(x : Field, y : pub u32) { +fn main(x: Field, y: pub u32) { let bytes = x.to_be_bytes(y); assert(bytes[0] == 0); } diff --git a/tooling/nargo_cli/tests/compile_failure/slice_access_failure/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/slice_access_failure/Nargo.toml index fee471dffd7..fc159b7efc1 100644 --- a/tooling/nargo_cli/tests/compile_failure/slice_access_failure/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/slice_access_failure/Nargo.toml @@ -2,6 +2,5 @@ name = "slice_access_failure" type = "bin" authors = [""] -compiler_version = "0.10.2" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/slice_access_failure/src/main.nr b/tooling/nargo_cli/tests/compile_failure/slice_access_failure/src/main.nr index dc651cd514d..6e8b5c7d841 100644 --- a/tooling/nargo_cli/tests/compile_failure/slice_access_failure/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/slice_access_failure/src/main.nr @@ -1,4 +1,4 @@ -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { let mut slice = [0; 2]; if x == y { slice = slice.push_back(y); diff --git a/tooling/nargo_cli/tests/compile_failure/slice_insert_failure/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/slice_insert_failure/Nargo.toml index fc7eb87be49..5134032264c 100644 --- a/tooling/nargo_cli/tests/compile_failure/slice_insert_failure/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/slice_insert_failure/Nargo.toml @@ -2,6 +2,4 @@ name = "slice_insert_failure" type = "bin" authors = [""] -compiler_version = "0.12.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/slice_insert_failure/src/main.nr b/tooling/nargo_cli/tests/compile_failure/slice_insert_failure/src/main.nr index dad80bff7ab..38892f01e12 100644 --- a/tooling/nargo_cli/tests/compile_failure/slice_insert_failure/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/slice_insert_failure/src/main.nr @@ -1,4 +1,4 @@ -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { let mut slice = [0; 2]; if x == y { slice = slice.push_back(y); @@ -8,4 +8,4 @@ fn main(x : Field, y : pub Field) { } slice = slice.insert(10, 100); -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/compile_failure/slice_remove_failure/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/slice_remove_failure/Nargo.toml index 795a4d863cb..1e13dfe6483 100644 --- a/tooling/nargo_cli/tests/compile_failure/slice_remove_failure/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/slice_remove_failure/Nargo.toml @@ -2,6 +2,4 @@ name = "slice_remove_failure" type = "bin" authors = [""] -compiler_version = "0.12.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/slice_remove_failure/src/main.nr b/tooling/nargo_cli/tests/compile_failure/slice_remove_failure/src/main.nr index 7c308488ae8..f9faa25384b 100644 --- a/tooling/nargo_cli/tests/compile_failure/slice_remove_failure/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/slice_remove_failure/src/main.nr @@ -1,4 +1,4 @@ -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { let mut slice = [0; 2]; if x == y { slice = slice.push_back(y); @@ -8,4 +8,4 @@ fn main(x : Field, y : pub Field) { } let (removed_slice, removed_elem) = slice.remove(10); -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/compile_failure/trait_incorrect_generic_count/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/trait_incorrect_generic_count/Nargo.toml new file mode 100644 index 00000000000..379e964d70a --- /dev/null +++ b/tooling/nargo_cli/tests/compile_failure/trait_incorrect_generic_count/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "trait_incorrect_generic_count" +type = "bin" +authors = [""] +compiler_version = ">=0.18.0" + +[dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_failure/trait_incorrect_generic_count/src/main.nr b/tooling/nargo_cli/tests/compile_failure/trait_incorrect_generic_count/src/main.nr new file mode 100644 index 00000000000..d65d55894ea --- /dev/null +++ b/tooling/nargo_cli/tests/compile_failure/trait_incorrect_generic_count/src/main.nr @@ -0,0 +1,12 @@ +fn main() { + let x: u32 = 0; + x.trait_fn(); +} + +trait Trait { + fn trait_fn(x: T) -> T {} +} + +impl Trait for u32 { + fn trait_fn(x: A) -> A { x } +} diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/Nargo.toml index 411f048a93b..8d0e1aca4a9 100644 --- a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/Nargo.toml @@ -2,6 +2,4 @@ name = "a" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/src/main.nr b/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/src/main.nr index 550e5034a7b..cf72627da2e 100644 --- a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/a/src/main.nr @@ -1,3 +1,3 @@ -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { assert(x == y); } diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/Nargo.toml index 1af8ef961cc..f316511340f 100644 --- a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/Nargo.toml @@ -2,6 +2,4 @@ name = "b" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/src/main.nr b/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/src/main.nr index 6e170de75fc..4e1fd3c9035 100644 --- a/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/src/main.nr +++ b/tooling/nargo_cli/tests/compile_failure/workspace_fail/crates/b/src/main.nr @@ -1,3 +1,3 @@ -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { assert(x != y); } diff --git a/tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/b/Nargo.toml b/tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/b/Nargo.toml index 1af8ef961cc..f316511340f 100644 --- a/tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/b/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_failure/workspace_missing_toml/crates/b/Nargo.toml @@ -2,6 +2,4 @@ name = "b" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_contract/contract_with_impl/Nargo.toml b/tooling/nargo_cli/tests/compile_success_contract/contract_with_impl/Nargo.toml index 99340cf80b5..ed5e9ec0910 100644 --- a/tooling/nargo_cli/tests/compile_success_contract/contract_with_impl/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_contract/contract_with_impl/Nargo.toml @@ -2,7 +2,6 @@ name = "simple_contract" type = "contract" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_contract/contract_with_impl/src/main.nr b/tooling/nargo_cli/tests/compile_success_contract/contract_with_impl/src/main.nr index fa04e0d3e7b..ddcb5d54d78 100644 --- a/tooling/nargo_cli/tests/compile_success_contract/contract_with_impl/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_contract/contract_with_impl/src/main.nr @@ -1,4 +1,3 @@ - contract Foo { struct T { x: [Field] } diff --git a/tooling/nargo_cli/tests/compile_success_contract/non_entry_point_method/Nargo.toml b/tooling/nargo_cli/tests/compile_success_contract/non_entry_point_method/Nargo.toml index c17e430c703..fb1969acc43 100644 --- a/tooling/nargo_cli/tests/compile_success_contract/non_entry_point_method/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_contract/non_entry_point_method/Nargo.toml @@ -2,6 +2,5 @@ name = "no_entry_points" type = "contract" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_contract/non_entry_point_method/src/main.nr b/tooling/nargo_cli/tests/compile_success_contract/non_entry_point_method/src/main.nr index 5c7152029c9..b768653262a 100644 --- a/tooling/nargo_cli/tests/compile_success_contract/non_entry_point_method/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_contract/non_entry_point_method/src/main.nr @@ -1,6 +1,6 @@ contract Foo { struct PlaceholderStruct{x : u32 } - + #[contract_library_method] - fn has_mut(_context : &mut PlaceholderStruct) {} -} \ No newline at end of file + fn has_mut(_context: &mut PlaceholderStruct) {} +} diff --git a/tooling/nargo_cli/tests/compile_success_contract/simple_contract/Nargo.toml b/tooling/nargo_cli/tests/compile_success_contract/simple_contract/Nargo.toml index 99340cf80b5..ed5e9ec0910 100644 --- a/tooling/nargo_cli/tests/compile_success_contract/simple_contract/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_contract/simple_contract/Nargo.toml @@ -2,7 +2,6 @@ name = "simple_contract" type = "contract" authors = [""] -compiler_version = "0.1" [dependencies] 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 index dd762ca3d21..88edd4ac2c3 100644 --- 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 @@ -1,6 +1,14 @@ 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 } + 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/attributes_multiple/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/attributes_multiple/Nargo.toml index 96b221d6c9b..78b0e5b7b18 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/attributes_multiple/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/attributes_multiple/Nargo.toml @@ -2,6 +2,5 @@ name = "attributes_multiple" type = "bin" authors = [""] -compiler_version = "0.10.5" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/attributes_multiple/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/attributes_multiple/src/main.nr index 46b761065ff..581fb989b4c 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/attributes_multiple/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/attributes_multiple/src/main.nr @@ -1,8 +1,7 @@ - fn main() { another_func() } #[aztec(private)] #[internal] -fn another_func() {} \ No newline at end of file +fn another_func() {} diff --git a/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml index 0f00e7d9c73..e05ccb8d925 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/attributes_struct/Nargo.toml @@ -2,6 +2,5 @@ name = "attributes_struct" type = "bin" authors = [""] -compiler_version = "0.11.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/auto_deref/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/auto_deref/Nargo.toml index cc1c9a8d8f7..ed2a51c0fb0 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/auto_deref/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/auto_deref/Nargo.toml @@ -2,6 +2,4 @@ name = "auto_deref" type = "bin" authors = [""] -compiler_version = "0.16.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/auto_deref/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/auto_deref/src/main.nr index e0b4a447fd0..d69aff7e0d4 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/auto_deref/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/auto_deref/src/main.nr @@ -1,4 +1,3 @@ - fn main() { let a = &mut &mut &mut [1, 2, 3]; assert(a[0] == 1); diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_cast/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/brillig_cast/Nargo.toml index 7c5aebabb95..cb5a7f3f2bd 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/brillig_cast/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/brillig_cast/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_cast" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_cast/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/brillig_cast/src/main.nr index e258a8f2640..3ba29b52982 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/brillig_cast/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/brillig_cast/src/main.nr @@ -1,7 +1,7 @@ // Tests a very simple Brillig function. // // The features being tested are cast operations on brillig -fn main() { +fn main() { bool_casts(); field_casts(); uint_casts(); @@ -40,7 +40,6 @@ unconstrained fn int_casts() { assert(x as i8 == 100); } - unconstrained fn mixed_casts() { assert(100 as u32 as i32 as u32 == 100); assert(13 as u4 as i2 as u32 == 1); diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/Nargo.toml index a8e7cd167d2..fb17e881f4c 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_field_binary_operations" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/src/main.nr index e7b0afccc3e..54f06858846 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/brillig_field_binary_operations/src/main.nr @@ -1,5 +1,5 @@ // Tests arithmetic operations on fields -fn main() { +fn main() { let x = 4; let y = 2; assert((x + y) == add(x, y)); @@ -8,18 +8,18 @@ fn main() { assert((x / y) == div(x, y)); } -unconstrained fn add(x : Field, y : Field) -> Field { +unconstrained fn add(x: Field, y: Field) -> Field { x + y } -unconstrained fn sub(x : Field, y : Field) -> Field { +unconstrained fn sub(x: Field, y: Field) -> Field { x - y } -unconstrained fn mul(x : Field, y : Field) -> Field { +unconstrained fn mul(x: Field, y: Field) -> Field { x * y } -unconstrained fn div(x : Field, y : Field) -> Field { +unconstrained fn div(x: Field, y: Field) -> Field { x / y -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/Nargo.toml index 09b851e7c5c..cd550ce0252 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_integer_binary_operations" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/src/main.nr index 72f614f1e63..a873bcd5dbd 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/brillig_integer_binary_operations/src/main.nr @@ -1,5 +1,5 @@ // Tests arithmetic operations on integers -fn main() { +fn main() { let x: u32 = 6; let y: u32 = 2; @@ -10,7 +10,6 @@ fn main() { assert((x * y) == mul(x, y)); assert((x / y) == div(x, y)); - // TODO SSA => ACIR has some issues with i32 ops assert(check_signed_div(6, 2, 3)); @@ -22,27 +21,25 @@ fn main() { assert((x & y) == and(x, y)); assert((x | y) == or(x, y)); - // TODO SSA => ACIR has some issues with xor ops - assert(check_xor(x, y, 4)); assert((x >> y) == shr(x, y)); assert((x << y) == shl(x, y)); } -unconstrained fn add(x : u32, y : u32) -> u32 { +unconstrained fn add(x: u32, y: u32) -> u32 { x + y } -unconstrained fn sub(x : u32, y : u32) -> u32 { +unconstrained fn sub(x: u32, y: u32) -> u32 { x - y } -unconstrained fn mul(x : u32, y : u32) -> u32 { +unconstrained fn mul(x: u32, y: u32) -> u32 { x * y } -unconstrained fn div(x : u32, y : u32) -> u32 { +unconstrained fn div(x: u32, y: u32) -> u32 { x / y } @@ -50,31 +47,31 @@ unconstrained fn check_signed_div(x: i32, y: i32, result: i32) -> bool { (x / y) == result } -unconstrained fn eq(x : u32, y : u32) -> bool { +unconstrained fn eq(x: u32, y: u32) -> bool { x == y } -unconstrained fn lt(x : u32, y : u32) -> bool { +unconstrained fn lt(x: u32, y: u32) -> bool { x < y } -unconstrained fn and(x : u32, y : u32) -> u32 { +unconstrained fn and(x: u32, y: u32) -> u32 { x & y } -unconstrained fn or(x : u32, y : u32) -> u32 { +unconstrained fn or(x: u32, y: u32) -> u32 { x | y } -unconstrained fn check_xor(x : u32, y : u32, result: u32) -> bool { +unconstrained fn check_xor(x: u32, y: u32, result: u32) -> bool { (x ^ y) == result } -unconstrained fn shr(x : u32, y : u32) -> u32 { +unconstrained fn shr(x: u32, y: u32) -> u32 { x >> y } -unconstrained fn shl(x : u32, y : u32) -> u32 { +unconstrained fn shl(x: u32, y: u32) -> u32 { x << y } diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/Nargo.toml index b27417dba8f..7bac4a06607 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_modulo" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/src/main.nr index c2c15f88b91..ed0353b101a 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/brillig_modulo/src/main.nr @@ -7,18 +7,15 @@ fn main() { assert(signed_modulo(5, 3) == 2); assert(signed_modulo(2, 3) == 2); - // See #3275. - // Commented out for now since the previous values which would overflow an i4 are now a compiler error. - // let minus_two: i4 = -2; // 14 - // let minus_three: i4 = -3; // 13 - // let minus_five: i4 = -5; // 11 - - // // (5 / -3) * -3 + 2 = -1 * -3 + 2 = 3 + 2 = 5 - // assert(signed_modulo(5, minus_three) == 2); - // // (-5 / 3) * 3 - 2 = -1 * 3 - 2 = -3 - 2 = -5 - // assert(signed_modulo(minus_five, 3) == minus_two); - // // (-5 / -3) * -3 - 2 = 1 * -3 - 2 = -3 - 2 = -5 - // assert(signed_modulo(minus_five, minus_three) == minus_two); + let minus_two: i4 = -2; // 14 + let minus_three: i4 = -3; // 13 + let minus_five: i4 = -5; // 11 + // (5 / -3) * -3 + 2 = -1 * -3 + 2 = 3 + 2 = 5 + assert(signed_modulo(5, minus_three) == 2); + // (-5 / 3) * 3 - 2 = -1 * 3 - 2 = -3 - 2 = -5 + assert(signed_modulo(minus_five, 3) == minus_two); + // (-5 / -3) * -3 - 2 = 1 * -3 - 2 = -3 - 2 = -5 + assert(signed_modulo(minus_five, minus_three) == minus_two); } unconstrained fn modulo(x: u32, y: u32) -> u32 { diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_to_bits/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/brillig_to_bits/Nargo.toml index 6c62900468a..a18b769550d 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/brillig_to_bits/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/brillig_to_bits/Nargo.toml @@ -2,6 +2,4 @@ name = "brillig_to_bits" type = "bin" authors = [""] -compiler_version = "0.7.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/brillig_to_bits/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/brillig_to_bits/src/main.nr index a2ab0d4bc5a..7ff3d2467b5 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/brillig_to_bits/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/brillig_to_bits/src/main.nr @@ -7,7 +7,7 @@ unconstrained fn main() { for i in 0..16 { let x = be_bits[i]; - let y = le_bits[15-i]; + let y = le_bits[15 - i]; assert(x == y); } @@ -17,8 +17,7 @@ unconstrained fn main() { for i in 0..4 { let be_bit = be_bits_x[i]; - let le_bit = le_bits_x[3-i]; + let le_bit = le_bits_x[3 - i]; assert(be_bit == le_bit); } - } diff --git a/tooling/nargo_cli/tests/compile_success_empty/closure_explicit_types/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/closure_explicit_types/Nargo.toml index 0ff85ab80bb..86ddff27910 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/closure_explicit_types/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/closure_explicit_types/Nargo.toml @@ -2,6 +2,5 @@ name = "closure_explicit_types" type = "bin" authors = [""] -compiler_version = "0.10.3" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/closure_explicit_types/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/closure_explicit_types/src/main.nr index 133bc1b4206..eec2b90b5b2 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/closure_explicit_types/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/closure_explicit_types/src/main.nr @@ -1,54 +1,45 @@ - fn ret_normal_lambda1() -> fn() -> Field { || 10 } - // return lamda that captures a thing fn ret_closure1() -> fn[(Field,)]() -> Field { let x = 20; || x + 10 } - // return lamda that captures two things fn ret_closure2() -> fn[(Field,Field)]() -> Field { let x = 20; let y = 10; || x + y + 10 } - // return lamda that captures two things with different types fn ret_closure3() -> fn[(u32,u64)]() -> u64 { let x: u32 = 20; let y: u64 = 10; || x as u64 + y + 10 } - // accepts closure that has 1 thing in its env, calls it and returns the result fn accepts_closure1(f: fn[(Field,)]() -> Field) -> Field { f() } - // accepts closure that has 1 thing in its env and returns it fn accepts_closure2(f: fn[(Field,)]() -> Field) -> fn[(Field,)]() -> Field { f } - // accepts closure with different types in the capture group fn accepts_closure3(f: fn[(u32, u64)]() -> u64) -> u64 { f() } - // generic over closure environments fn add_results(f1: fn[Env1]() -> Field, f2: fn[Env2]() -> Field) -> Field { f1() + f2() } - // a *really* generic function fn map(arr: [T; N], f: fn[Env](T) -> U) -> [U; N] { let first_elem = f(arr[0]); let mut ret = [first_elem; N]; - for i in 1 .. N { + for i in 1..N { ret[i] = f(arr[i]); } @@ -70,10 +61,10 @@ fn main() { assert(accepts_closure3(|| y as u64 + z) == 70); let w = 50; - assert(add_results(|| 100, || x ) == 150); - assert(add_results(|| x + 100, || w + x ) == 250); + assert(add_results(|| 100, || x) == 150); + assert(add_results(|| x + 100, || w + x) == 250); - let arr = [1,2,3,4]; + let arr = [1, 2, 3, 4]; assert(map(arr, |n| n + 1) == [2, 3, 4, 5]); assert(map(arr, |n| n + x) == [51, 52, 53, 54]); diff --git a/tooling/nargo_cli/tests/compile_success_empty/comptime_recursion_regression/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/comptime_recursion_regression/Nargo.toml index 6ded8f92d55..74710a6ac2a 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/comptime_recursion_regression/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/comptime_recursion_regression/Nargo.toml @@ -2,6 +2,5 @@ name = "comptime_recursion_regression" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/comptime_sort/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/comptime_sort/Nargo.toml index 15221af78c8..7d215a22496 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/comptime_sort/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/comptime_sort/Nargo.toml @@ -2,6 +2,4 @@ name = "comptime_sort" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/comptime_sort/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/comptime_sort/src/main.nr index f8bd38654c0..a24a6ebaba6 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/comptime_sort/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/comptime_sort/src/main.nr @@ -1,6 +1,5 @@ - fn main() { - let unsorted: [u8; 3] = [3,1,2]; + let unsorted: [u8; 3] = [3, 1, 2]; let sorted = unsorted.sort(); assert(sorted[0] == 1); assert(sorted[1] == 2); diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/Nargo.toml index 2729aca911c..1a62c5af20c 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/Nargo.toml @@ -2,6 +2,5 @@ name = "conditional_regression_547" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/src/main.nr index 41ccbb00a2a..e47d23516a5 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_547/src/main.nr @@ -7,16 +7,10 @@ fn main(x: Field) -> pub Field { assert(i != 2); } } - // Regression for predicate simplification x + safe_inverse(0) } fn safe_inverse(n: Field) -> Field { - if n == 0 { - 0 - } - else { - 1 / n - } + if n == 0 { 0 } else { 1 / n } } diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_579/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_579/Nargo.toml index fab92005fba..b440cb26e46 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_579/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_579/Nargo.toml @@ -2,6 +2,5 @@ name = "conditional_regression_579" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/Nargo.toml index e886f083a6c..f2b13c4d547 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/Nargo.toml @@ -2,6 +2,5 @@ name = "conditional_regression_to_bits" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/src/main.nr index e5450334c5e..5446cfbb1e4 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/conditional_regression_to_bits/src/main.nr @@ -11,13 +11,13 @@ fn main() { c1 = c1 + as_bits[0] as Field; if i == 0 { - assert(arr[i] == 1);// 1 + assert(arr[i] == 1); // 1 for k in 0..2 { assert(as_bits_hardcode_1[k] == as_bits[k]); } } if i == 1 { - assert(arr[i] == 2);//2 + assert(arr[i] == 2); //2 for k in 0..2 { assert(as_bits_hardcode_1[k] != as_bits[k]); } diff --git a/tooling/nargo_cli/tests/compile_success_empty/ec_baby_jubjub/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/ec_baby_jubjub/Nargo.toml index 178be37f780..fdb0df17112 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/ec_baby_jubjub/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/ec_baby_jubjub/Nargo.toml @@ -3,6 +3,5 @@ name = "ec_baby_jubjub" description = "Baby Jubjub sanity checks" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] 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 index 3372e969d4b..e7f32999454 100644 --- 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 @@ -1,5 +1,4 @@ // 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; @@ -13,77 +12,58 @@ 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 - { + if 21888242871839275222246405745257275088548364400416034343698204186575808495617 == 0 { // Define Baby Jubjub (ERC-2494) parameters in affine representation - let bjj_affine = AffineCurve::new(168700, 168696, Gaffine::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); - + 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 - )) - ); + 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))); - + 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) - ); - + 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(); - + 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))); - + 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) - ); - + 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(); @@ -93,35 +73,21 @@ fn main() { 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 - ) - ) - ); - + 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))); - + 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) - ); - + 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(); @@ -130,28 +96,21 @@ fn main() { 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))); - + 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))); - + 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) - ); - + 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(); @@ -161,28 +120,21 @@ fn main() { 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))); - + 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) - ); - + 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(); @@ -191,36 +143,32 @@ fn main() { 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))); - + 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) - ); - + 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())); - + 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)))); - } + 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/tooling/nargo_cli/tests/compile_success_empty/generators/Nargo.toml index 0f05b6e5759..58d8a993e16 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/generators/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/generators/Nargo.toml @@ -2,6 +2,5 @@ name = "generators" type = "bin" authors = [""] -compiler_version = "0.10.3" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/generators/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/generators/src/main.nr index 2f6f90a8c57..20bdedee50f 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/generators/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/generators/src/main.nr @@ -25,10 +25,9 @@ fn fibonacci_generator() -> fn[(&mut Field, &mut Field)]() -> Field { old_x } } - // we'll be able to un-hardcode the array length if we have the ::<> syntax proposed in https://github.com/noir-lang/noir/issues/2458 fn get_some(generator: fn[Env]() -> Field) -> [Field; 5] { - [0,0,0,0,0].map(|_| generator()) + [0, 0, 0, 0, 0].map(|_| generator()) } fn test_fib() { @@ -44,9 +43,9 @@ fn test_fib() { fn test_counter() { let counter = make_counter(); - assert(counter() == 1); - assert(counter() == 2); - assert(counter() == 3); + assert(counter() == 1); + assert(counter() == 2); + assert(counter() == 3); assert(get_some(counter) == [4, 5, 6, 7, 8]); } diff --git a/tooling/nargo_cli/tests/compile_success_empty/higher_order_fn_selector/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/higher_order_fn_selector/Nargo.toml index 09a0e342a71..968fc5300e6 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/higher_order_fn_selector/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/higher_order_fn_selector/Nargo.toml @@ -2,6 +2,4 @@ name = "higher_order_fn_selector" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/higher_order_fn_selector/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/higher_order_fn_selector/src/main.nr index e1a13919f4c..99093c581b5 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/higher_order_fn_selector/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/higher_order_fn_selector/src/main.nr @@ -1,4 +1,3 @@ - fn g(x: &mut Field) -> () { *x *= 2; } @@ -8,19 +7,13 @@ fn h(x: &mut Field) -> () { } fn selector(flag: &mut bool) -> fn(&mut Field) -> () { - let my_func = if *flag { - g - } else { - h - }; - + let my_func = if *flag { g } else { h }; // Flip the flag for the next function call *flag = !(*flag); my_func } fn main() { - let mut flag: bool = true; let mut x: Field = 100; @@ -34,5 +27,4 @@ fn main() { returned_func2(&mut y); assert(y == 300); - } diff --git a/tooling/nargo_cli/tests/compile_success_empty/impl_with_where_clause/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/impl_with_where_clause/Nargo.toml new file mode 100644 index 00000000000..ef9bdce2640 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/impl_with_where_clause/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "impl_with_where_clause" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/impl_with_where_clause/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/impl_with_where_clause/src/main.nr new file mode 100644 index 00000000000..de3078be8ba --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/impl_with_where_clause/src/main.nr @@ -0,0 +1,27 @@ +fn main() { + let array: [Field; 3] = [1, 2, 3]; + assert(array.eq(array)); + // Ensure this still works if we have to infer the type of the integer literals + let array = [1, 2, 3]; + assert(array.eq(array)); +} + +trait Eq { + fn eq(self, other: Self) -> bool; +} + +impl Eq for [T; 3] where T: Eq { + fn eq(self, other: Self) -> bool { + let mut ret = true; + for i in 0 .. self.len() { + ret &= self[i].eq(other[i]); + } + ret + } +} + +impl Eq for Field { + fn eq(self, other: Field) -> bool { + self == other + } +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/inner_outer_cl/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/inner_outer_cl/Nargo.toml index 25722866d9b..073456fa7f6 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/inner_outer_cl/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/inner_outer_cl/Nargo.toml @@ -2,6 +2,5 @@ name = "inner_outer_cl" type = "bin" authors = [""] -compiler_version = "0.7.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/Nargo.toml index 615bc6254e2..4786a87ff65 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/Nargo.toml @@ -2,6 +2,4 @@ name = "instruction_deduplication" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/src/main.nr index 09aa8ee47f2..43c0a382185 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/instruction_deduplication/src/main.nr @@ -1,4 +1,4 @@ -fn main(x : Field) { +fn main(x: Field) { // This is a regression test for #2450. // The compiler should recognize that the `(x as u32)` instructions are duplicates and so have the same output. assert(x as u32 == x as u32); diff --git a/tooling/nargo_cli/tests/compile_success_empty/intrinsic_die/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/intrinsic_die/Nargo.toml index 60e0310eab2..539c536b944 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/intrinsic_die/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/intrinsic_die/Nargo.toml @@ -2,6 +2,4 @@ name = "intrinsic_die" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/intrinsic_die/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/intrinsic_die/src/main.nr index 08c5cce4034..88f7a3634c1 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/intrinsic_die/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/intrinsic_die/src/main.nr @@ -1,11 +1,8 @@ use dep::std; - // This test checks that we perform dead-instruction-elimination on intrinsic functions. - fn main(x: Field) { let bytes = x.to_be_bytes(32); - - let hash = std::hash::pedersen([x]); - let _p1 = std::scalar_mul::fixed_base_embedded_curve(x, 0); + let hash = std::hash::pedersen_commitment([x]); + let _p1 = std::scalar_mul::fixed_base_embedded_curve(x, 0); } diff --git a/tooling/nargo_cli/tests/compile_success_empty/let_stmt/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/let_stmt/Nargo.toml index 45f9a53edeb..def6e33b39a 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/let_stmt/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/let_stmt/Nargo.toml @@ -2,6 +2,4 @@ name = "let_stmt" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/main_return/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/main_return/Nargo.toml index c4224b7e23c..793ae612730 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/main_return/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/main_return/Nargo.toml @@ -2,6 +2,5 @@ name = "main_return" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/numeric_generics/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/numeric_generics/Nargo.toml index c8a3ce73a5e..835c945c3b8 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/numeric_generics/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/numeric_generics/Nargo.toml @@ -2,6 +2,5 @@ name = "numeric_generics" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/option/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/option/Nargo.toml index 553efccd746..d9bec3c3096 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/option/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/option/Nargo.toml @@ -2,6 +2,4 @@ name = "option" type = "bin" authors = [""] -compiler_version = "0.7.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/option/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/option/src/main.nr index 22229014eef..1f879bd375f 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/option/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/option/src/main.nr @@ -2,7 +2,6 @@ use dep::std::option::Option; fn main() { let ten = 10; // giving this a name, to ensure that the Option functions work with closures - let none = Option::none(); let some = Option::some(3); diff --git a/tooling/nargo_cli/tests/compile_success_empty/references_aliasing/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/references_aliasing/Nargo.toml index b95c3998483..0310e55ed7e 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/references_aliasing/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/references_aliasing/Nargo.toml @@ -2,6 +2,5 @@ name = "references_aliasing" type = "bin" authors = [""] -compiler_version = "0.5.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/references_aliasing/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/references_aliasing/src/main.nr index 02057732f35..0d96bc2a734 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/references_aliasing/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/references_aliasing/src/main.nr @@ -10,7 +10,6 @@ fn main() { fn increment(mut r: &mut Field) { *r = *r + 1; } - // If aliasing within arrays and constant folding within the mem2reg pass aren't // handled, we'll fail to optimize out all the references in this function. fn regression_2445() { diff --git a/tooling/nargo_cli/tests/compile_success_empty/regression_2099/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/regression_2099/Nargo.toml index 3e995a0acd6..6b9f9a24038 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/regression_2099/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/regression_2099/Nargo.toml @@ -2,6 +2,4 @@ name = "regression_2099" type = "bin" authors = [""] -compiler_version = "0.9.0" - [dependencies] 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 index b96e664dedf..185a6426cb3 100644 --- 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 @@ -11,13 +11,16 @@ 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)); - + 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 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(); @@ -25,13 +28,7 @@ fn main() { 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 - ); - + 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) - ); + 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/tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/Nargo.toml index 4e1b06d927f..4f778574417 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/Nargo.toml @@ -2,6 +2,5 @@ name = "ret_fn_ret_cl" type = "bin" authors = [""] -compiler_version = "0.7.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/src/main.nr index a368dc58529..89083b076b6 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/ret_fn_ret_cl/src/main.nr @@ -5,7 +5,6 @@ fn f(x: Field) -> Field { fn ret_fn() -> fn(Field) -> Field { f } - // TODO: in the advanced implicitly generic function with closures branch // which would support higher-order functions in a better way // support returning closures: @@ -17,7 +16,6 @@ fn ret_fn() -> fn(Field) -> Field { // }; // inner_closure // } - fn ret_lambda() -> fn(Field) -> Field { let cl = |z: Field| -> Field { z + 1 @@ -25,13 +23,11 @@ fn ret_lambda() -> fn(Field) -> Field { cl } -fn main(x : Field) { +fn main(x: Field) { let result_fn = ret_fn(); assert(result_fn(x) == x + 1); - // let result_closure = ret_closure(); // assert(result_closure(x) == x + 1); - let result_lambda = ret_lambda(); assert(result_lambda(x) == x + 1); } diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_array_param/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/simple_array_param/Nargo.toml index 9874c8cb6a8..4f1811cc669 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/simple_array_param/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/simple_array_param/Nargo.toml @@ -2,6 +2,4 @@ name = "simple_array_param" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_array_param/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/simple_array_param/src/main.nr index 60978bab519..6dd7c34dab5 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/simple_array_param/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/simple_array_param/src/main.nr @@ -1,6 +1,6 @@ // This program tests: // - the allocation of virtual arrays for array params to main // - load instructions for such arrays -fn main(xs : [Field; 2]) -> pub Field { +fn main(xs: [Field; 2]) -> pub Field { xs[1] } diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/Nargo.toml index f35a196ab59..13178336eea 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/Nargo.toml @@ -2,6 +2,5 @@ name = "simple_program_no_body" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/src/main.nr index b87f216b461..21719018f3f 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/simple_program_no_body/src/main.nr @@ -6,4 +6,4 @@ // // This program will never fail since there are // no assertions being applied. -fn main(_x : Field, _y : pub Field) {} \ No newline at end of file +fn main(_x: Field, _y: pub Field) {} diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_range/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/simple_range/Nargo.toml index 864cd03beb3..1db9099be7e 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/simple_range/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/simple_range/Nargo.toml @@ -2,6 +2,5 @@ name = "simple_range" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/simple_range/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/simple_range/src/main.nr index 9a4b9033493..3f595cfd817 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/simple_range/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/simple_range/src/main.nr @@ -1,6 +1,6 @@ // Tests a very simple program. // // The features being tested is casting to an integer -fn main(x : Field) { +fn main(x: Field) { let _z = x as u32; -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/specialization/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/specialization/Nargo.toml index df379491dc9..aaccd85a444 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/specialization/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/specialization/Nargo.toml @@ -2,6 +2,4 @@ name = "specialization" type = "bin" authors = [""] -compiler_version = "0.16.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/specialization/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/specialization/src/main.nr index 32102ad1437..9cd32e0f1eb 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/specialization/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/specialization/src/main.nr @@ -9,7 +9,7 @@ impl Foo { } fn main() { - let f1: Foo = Foo{}; - let f2: Foo = Foo{}; + let f1: Foo = Foo {}; + let f2: Foo = Foo {}; assert(f1.foo() + f2.foo() == 3); } diff --git a/tooling/nargo_cli/tests/compile_success_empty/str_as_bytes/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/str_as_bytes/Nargo.toml index 31f7ab5d9b4..6b9bbd9b65f 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/str_as_bytes/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/str_as_bytes/Nargo.toml @@ -2,6 +2,4 @@ name = "str_as_bytes" type = "bin" authors = [""] -compiler_version = "0.9.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/str_as_bytes/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/str_as_bytes/src/main.nr index 6890b156b15..6fdd926ce7f 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/str_as_bytes/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/str_as_bytes/src/main.nr @@ -2,17 +2,17 @@ use dep::std; fn main() { let a = "hello"; let b = a.as_bytes(); - assert(b[0]==104); - assert(b[1]==101); - assert(b[2]==108); - assert(b[3]==108); - assert(b[4]==111); - assert(b.len()==5); + assert(b[0] == 104); + assert(b[1] == 101); + assert(b[2] == 108); + assert(b[3] == 108); + assert(b[4] == 111); + assert(b.len() == 5); let mut c = a.as_bytes_vec(); - assert(c.get(0)==104); - assert(c.get(1)==101); - assert(c.get(2)==108); - assert(c.get(3)==108); - assert(c.get(4)==111); - assert(c.len()==5); + assert(c.get(0) == 104); + assert(c.get(1) == 101); + assert(c.get(2) == 108); + assert(c.get(3) == 108); + assert(c.get(4) == 111); + assert(c.len() == 5); } diff --git a/tooling/nargo_cli/tests/compile_success_empty/to_bits/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/to_bits/Nargo.toml index 9fe822eca93..ef47f3b4ba1 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/to_bits/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/to_bits/Nargo.toml @@ -2,6 +2,4 @@ name = "to_bits" type = "bin" authors = [""] -compiler_version = "0.7.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/to_bits/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/to_bits/src/main.nr index 65ff9dcac01..84ace83903a 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/to_bits/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/to_bits/src/main.nr @@ -1,4 +1,3 @@ - fn main() { let field = 1000; let be_bits = field.to_be_bits(16); @@ -6,7 +5,7 @@ fn main() { for i in 0..16 { let x = be_bits[i]; - let y = le_bits[15-i]; + let y = le_bits[15 - i]; assert(x == y); } @@ -16,8 +15,7 @@ fn main() { for i in 0..4 { let be_bit = be_bits_x[i]; - let le_bit = le_bits_x[3-i]; + let le_bit = le_bits_x[3 - i]; assert(be_bit == le_bit); } - } diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/Nargo.toml index 459cf96bab7..bd31596297a 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/Nargo.toml @@ -2,6 +2,4 @@ name = "trait_allowed_item_name_matches" type = "bin" authors = [""] -compiler_version = "0.15.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/src/main.nr index 7db61e854fc..44cad58c2a6 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_allowed_item_name_matches/src/main.nr @@ -22,5 +22,4 @@ trait Trait4 { type Tralala; } -fn main() { -} +fn main() {} diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_associated_member_names_clashes/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/trait_associated_member_names_clashes/Nargo.toml index 585dcde7351..79d78c1aa51 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_associated_member_names_clashes/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_associated_member_names_clashes/Nargo.toml @@ -2,6 +2,4 @@ name = "trait_associated_member_names_clashes" type = "bin" authors = [""] -compiler_version = "0.16.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_default_implementation/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/trait_default_implementation/Nargo.toml index 7fcb4d0281e..938e224ec02 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_default_implementation/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_default_implementation/Nargo.toml @@ -2,6 +2,5 @@ name = "trait_default_implementation" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/Nargo.toml index 74be9decefc..1bb7522d6e1 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/Nargo.toml @@ -2,6 +2,4 @@ name = "trait_function_calls" type = "bin" authors = [""] -compiler_version = "0.15.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/src/main.nr index a3a19fe9dec..39d28a5a3b3 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_function_calls/src/main.nr @@ -1,9 +1,7 @@ // a more thorough test for trait function/method calls from within trait function/method calls - // This tests all combinations of caller+callee pairs. For each of these, the following combination of properties are tried: // *) method (has self parameter) vs function (no self parameter) // *) default vs overriden vs overriden (no default) - // test order is: // 1) trait method -> trait method // 1a) trait default method -> trait default method @@ -21,7 +19,6 @@ // 2i) // 3{a..i}) trait function -> trait method // 4{a..i}) trait function -> trait function - // 1) trait method -> trait method // 1a) trait default method -> trait default method trait Trait1a { @@ -34,7 +31,6 @@ trait Trait1a { } struct Struct1a { vl: Field } impl Trait1a for Struct1a { } - // 1b) trait default method -> trait overriden method trait Trait1b { fn trait_method1(self) -> Field { @@ -50,7 +46,6 @@ impl Trait1b for Struct1b { 2394 } } - // 1c) trait default method -> trait overriden (no default) method trait Trait1c { fn trait_method1(self) -> Field { @@ -64,7 +59,6 @@ impl Trait1c for Struct1c { 5485 } } - // 1d) trait overriden method -> trait default method trait Trait1d { fn trait_method1(self) -> Field { @@ -80,7 +74,6 @@ impl Trait1d for Struct1d { self.trait_method2() * 9342 - self.vl } } - // 1e) trait overriden method -> trait overriden method trait Trait1e { fn trait_method1(self) -> Field { @@ -99,7 +92,6 @@ impl Trait1e for Struct1e { 58945 } } - // 1f) trait overriden method -> trait overriden (no default) method trait Trait1f { fn trait_method1(self) -> Field { @@ -116,7 +108,6 @@ impl Trait1f for Struct1f { 5748 } } - // 1g) trait overriden (no default) method -> trait default method trait Trait1g { fn trait_method1(self) -> Field; @@ -130,7 +121,6 @@ impl Trait1g for Struct1g { self.trait_method2() * 7854 - self.vl } } - // 1h) trait overriden (no default) method -> trait overriden method trait Trait1h { fn trait_method1(self) -> Field; @@ -147,7 +137,6 @@ impl Trait1h for Struct1h { 8542 } } - // 1i) trait overriden (no default) method -> trait overriden (no default) method trait Trait1i { fn trait_method1(self) -> Field; @@ -162,7 +151,6 @@ impl Trait1i for Struct1i { 98543 } } - // 2) trait method -> trait function // 2a) trait default method -> trait default function trait Trait2a { @@ -175,7 +163,6 @@ trait Trait2a { } struct Struct2a { vl: Field } impl Trait2a for Struct2a { } - // 2b) trait default method -> trait overriden function trait Trait2b { fn trait_method1(self) -> Field { @@ -191,7 +178,6 @@ impl Trait2b for Struct2b { 8477 } } - // 2c) trait default method -> trait overriden (no default) function trait Trait2c { fn trait_method1(self) -> Field { @@ -205,7 +191,6 @@ impl Trait2c for Struct2c { 8342 } } - // 2d) trait overriden method -> trait default function trait Trait2d { fn trait_method1(self) -> Field { @@ -221,7 +206,6 @@ impl Trait2d for Struct2d { Self::trait_function2() * 3984 - self.vl } } - // 2e) trait overriden method -> trait overriden function trait Trait2e { fn trait_method1(self) -> Field { @@ -240,7 +224,6 @@ impl Trait2e for Struct2e { 39400 } } - // 2f) trait overriden method -> trait overriden (no default) function trait Trait2f { fn trait_method1(self) -> Field { @@ -257,7 +240,6 @@ impl Trait2f for Struct2f { 72311 } } - // 2g) trait overriden (no default) method -> trait default function trait Trait2g { fn trait_method1(self) -> Field; @@ -271,7 +253,6 @@ impl Trait2g for Struct2g { Self::trait_function2() * 9123 - self.vl } } - // 2h) trait overriden (no default) method -> trait overriden function trait Trait2h { fn trait_method1(self) -> Field; @@ -288,7 +269,6 @@ impl Trait2h for Struct2h { 5335 } } - // 2i) trait overriden (no default) method -> trait overriden (no default) function trait Trait2i { fn trait_method1(self) -> Field; @@ -303,7 +283,6 @@ impl Trait2i for Struct2i { 3322 } } - // 3 trait function -> trait method // 3a) trait default function -> trait default method trait Trait3a { @@ -316,7 +295,6 @@ trait Trait3a { } struct Struct3a { vl: Field } impl Trait3a for Struct3a { } - // 3b) trait default function -> trait overriden method trait Trait3b { fn trait_function1(a: Field, b: Self) -> Field { @@ -332,7 +310,6 @@ impl Trait3b for Struct3b { 2392 } } - // 3c) trait default function -> trait overriden (no default) method trait Trait3c { fn trait_function1(a: Field, b: Self) -> Field { @@ -346,7 +323,6 @@ impl Trait3c for Struct3c { 7743 } } - // 3d) trait overriden function -> trait default method trait Trait3d { fn trait_function1(a: Field, b: Self) -> Field { @@ -362,7 +338,6 @@ impl Trait3d for Struct3d { b.trait_method2() * 4933 - b.vl + a } } - // 3e) trait overriden function -> trait overriden method trait Trait3e { fn trait_function1(a: Field, b: Self) -> Field { @@ -381,7 +356,6 @@ impl Trait3e for Struct3e { 80002 } } - // 3f) trait overriden function -> trait overriden (no default) method trait Trait3f { fn trait_function1(a: Field, b: Self) -> Field { @@ -398,7 +372,6 @@ impl Trait3f for Struct3f { 63532 } } - // 3g) trait overriden (no default) function -> trait default method trait Trait3g { fn trait_function1(a: Field, b: Self) -> Field; @@ -412,7 +385,6 @@ impl Trait3g for Struct3g { b.trait_method2() * 31337 - b.vl + a } } - // 3h) trait overriden (no default) function -> trait overriden method trait Trait3h { fn trait_function1(a: Field, b: Self) -> Field; @@ -429,7 +401,6 @@ impl Trait3h for Struct3h { 6283 } } - // 3i) trait overriden (no default) function -> trait overriden (no default) method trait Trait3i { fn trait_function1(a: Field, b: Self) -> Field; @@ -444,7 +415,6 @@ impl Trait3i for Struct3i { 84352 } } - // 4) trait function -> trait function // 4a) trait default function -> trait default function trait Trait4a { @@ -457,7 +427,6 @@ trait Trait4a { } struct Struct4a { vl: Field } impl Trait4a for Struct4a { } - // 4b) trait default function -> trait overriden function trait Trait4b { fn trait_function1() -> Field { @@ -473,7 +442,6 @@ impl Trait4b for Struct4b { 9353 } } - // 4c) trait default function -> trait overriden (no default) function trait Trait4c { fn trait_function1() -> Field { @@ -487,7 +455,6 @@ impl Trait4c for Struct4c { 2928 } } - // 4d) trait overriden function -> trait default function trait Trait4d { fn trait_function1() -> Field { @@ -503,7 +470,6 @@ impl Trait4d for Struct4d { Self::trait_function2() * 8374 } } - // 4e) trait overriden function -> trait overriden function trait Trait4e { fn trait_function1() -> Field { @@ -522,7 +488,6 @@ impl Trait4e for Struct4e { 38434 } } - // 4f) trait overriden function -> trait overriden (no default) function trait Trait4f { fn trait_function1() -> Field { @@ -539,7 +504,6 @@ impl Trait4f for Struct4f { 4394 } } - // 4g) trait overriden (no default) function -> trait default function trait Trait4g { fn trait_function1() -> Field; @@ -553,7 +517,6 @@ impl Trait4g for Struct4g { Self::trait_function2() * 3345 } } - // 4h) trait overriden (no default) function -> trait overriden function trait Trait4h { fn trait_function1() -> Field; @@ -570,7 +533,6 @@ impl Trait4h for Struct4h { 5435 } } - // 4i) trait overriden (no default) function -> trait overriden (no default) function trait Trait4i { fn trait_function1() -> Field; @@ -586,7 +548,6 @@ impl Trait4i for Struct4i { } } - fn main() { let t1a = Struct1a { vl: 1234 }; assert(t1a.trait_method1() == 341548742); diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_generics/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/trait_generics/Nargo.toml new file mode 100644 index 00000000000..c1b5d0aaa6c --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_generics/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "trait_generics" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_generics/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/trait_generics/src/main.nr new file mode 100644 index 00000000000..bb6d6e74726 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_generics/src/main.nr @@ -0,0 +1,59 @@ +struct Empty {} + +trait Foo { + fn foo(self) -> u32; +} + +impl Foo for Empty { + fn foo(_self: Self) -> u32 { 32 } +} + +impl Foo for Empty { + fn foo(_self: Self) -> u32 { 64 } +} + +fn main() { + let x: Empty = Empty {}; + let y: Empty = Empty {}; + let z = Empty {}; + + assert(x.foo() == 32); + assert(y.foo() == 64); + // Types matching multiple impls will currently choose + // the first matching one instead of erroring + assert(z.foo() == 32); + + call_impl_with_generic_struct(); + call_impl_with_generic_function(); +} +// Ensure we can call a generic impl +fn call_impl_with_generic_struct() { + let x: u8 = 7; + let y: i8 = 8; + let s2_u8 = S2 { x }; + let s2_i8 = S2 { x: y }; + assert(s2_u8.t2().x == 7); + assert(s2_i8.t2().x == 8); +} + +trait T2 { + fn t2(self) -> Self; +} + +struct S2 { x: T } + +impl T2 for S2 { + fn t2(self) -> Self { self } +} + +fn call_impl_with_generic_function() { + assert(3.t3(7) == 7); +} + +trait T3 { + fn t3(self, x: T) -> T; +} + +impl T3 for u32 { + fn t3(self, y: U) -> U { y } +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/Nargo.toml index 89d83e18f66..efa176099cf 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/Nargo.toml @@ -2,6 +2,5 @@ name = "trait_multi_module_test" type = "bin" authors = [""] -compiler_version = "0.11.1" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module3.nr b/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module3.nr index 4b2fbc9bfcc..2485a2ba7a1 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module3.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_multi_module_test/src/module3.nr @@ -1,5 +1,4 @@ use crate::module1::MyTrait; use crate::module2::MyStruct; - // ensure we can implement traits that are imported with the `use` syntax impl MyTrait for MyStruct {} diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/Nargo.toml index 7ab5a62b5ba..1ccf15adc14 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/Nargo.toml @@ -2,6 +2,5 @@ name = "trait_override_implementation" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/src/main.nr index f5f01c79ad6..a385efc63fd 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_override_implementation/src/main.nr @@ -4,9 +4,8 @@ trait Default { fn default(x: Field, y: Field) -> Self; fn method2(x: Field) -> Field { - x + x } - } struct Foo { @@ -20,7 +19,7 @@ impl Default for Foo { } fn method2(x: Field) -> Field { - x * 3 + x * 3 } } @@ -39,33 +38,34 @@ impl F for Bar { fn f1(self) -> Field { 10 } fn f3(self) -> Field { 30 } } - -impl F for &mut Bar { - fn f1(self) -> Field { 101 } - fn f5(self) -> Field { 505 } -} - +// Impls on mutable references are temporarily disabled +// impl F for &mut Bar { +// fn f1(self) -> Field { 101 } +// fn f5(self) -> Field { 505 } +// } fn main(x: Field) { let first = Foo::method2(x); assert(first == 3 * x); - let bar = Bar{}; - assert(bar.f1() == 10); - assert(bar.f2() == 2); - assert(bar.f3() == 30); - assert(bar.f4() == 4); - assert(bar.f5() == 50); + let bar = Bar {}; + + assert(bar.f1() == 10, "1"); + assert(bar.f2() == 2, "2"); + assert(bar.f3() == 30, "3"); + assert(bar.f4() == 4, "4"); + assert(bar.f5() == 50, "5"); - let mut bar_mut = Bar{}; - assert((&mut bar_mut).f1() == 101); - assert((&mut bar_mut).f2() == 2); - assert((&mut bar_mut).f3() == 3); - assert((&mut bar_mut).f4() == 4); - assert((&mut bar_mut).f5() == 505); + let mut bar_mut = Bar {}; + // Impls on mutable references are temporarily disabled + // assert_eq((&mut bar_mut).f1(), 101); + // assert((&mut bar_mut).f2() == 2, "7"); + // assert((&mut bar_mut).f3() == 3, "8"); + // assert((&mut bar_mut).f4() == 4, "9"); + // assert((&mut bar_mut).f5() == 505, "10"); + assert(bar_mut.f1() == 10, "10"); + assert(bar_mut.f2() == 2, "12"); + assert(bar_mut.f3() == 30, "13"); + assert(bar_mut.f4() == 4, "14"); + assert(bar_mut.f5() == 50, "15"); +} - assert(bar_mut.f1() == 10); - assert(bar_mut.f2() == 2); - assert(bar_mut.f3() == 30); - assert(bar_mut.f4() == 4); - assert(bar_mut.f5() == 50); -} \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_self/trait_self/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/trait_self/trait_self/src/main.nr deleted file mode 100644 index f4f73822cc3..00000000000 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_self/trait_self/src/main.nr +++ /dev/null @@ -1,18 +0,0 @@ -struct Foo { - x: Field -} - -trait Asd { - fn asd() -> Self; -} - -impl Asd for Foo { - // the Self should typecheck properly - fn asd() -> Self { - Foo{x: 100} - } -} - -fn main() { - assert(Foo::asd().x == 100); -} \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_self/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/trait_static_methods/Nargo.toml similarity index 72% rename from tooling/nargo_cli/tests/compile_success_empty/trait_self/Nargo.toml rename to tooling/nargo_cli/tests/compile_success_empty/trait_static_methods/Nargo.toml index 0dfaea44862..71c541ccd4f 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_self/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_static_methods/Nargo.toml @@ -2,6 +2,5 @@ name = "trait_self" type = "bin" authors = [""] -compiler_version = "0.10.5" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_self/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/trait_static_methods/src/main.nr similarity index 99% rename from tooling/nargo_cli/tests/compile_success_empty/trait_self/src/main.nr rename to tooling/nargo_cli/tests/compile_success_empty/trait_static_methods/src/main.nr index 5bc372ba09b..0150da68315 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_self/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_static_methods/src/main.nr @@ -38,4 +38,4 @@ impl ATrait for Bar { fn main() { assert(Foo::static_method() == 100); assert(Bar::static_method() == 200); -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/Nargo.toml index 9f17579976b..1bbde8bfd79 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/Nargo.toml @@ -2,6 +2,5 @@ name = "trait_where_clause" type = "bin" authors = [""] -compiler_version = "0.11.1" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/src/main.nr index 891290061c6..5fd7e78abf4 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/src/main.nr @@ -1,10 +1,7 @@ -// TODO(#2568): Currently we only support trait constraints on free functions. +// TODO(#2568): Currently we only support trait constraints in a few cases. // There's a bunch of other places where they can pop up: // - trait methods (trait Foo where T: ... { ) -// - free impl blocks (impl Foo where T...) -// - trait impl blocks (impl Foo for Bar where T...) // - structs (struct Foo where T: ...) - // import the traits from another module to ensure the where clauses are ok with that mod the_trait; use crate::the_trait::Asd; @@ -27,7 +24,7 @@ impl Asd for AddXY { struct Static100 {} impl StaticTrait for Static100 { - // use default implementatino for static_function, which returns 100 + // use default implementation for static_function, which returns 100 } struct Static200 {} @@ -44,16 +41,16 @@ fn add_one_to_static_function(t: T) -> Field where T: StaticTrait { } fn main() { - let x = Add10{ x: 90 }; - let z = Add20{ x: 80 }; - let a = Add30{ x: 70 }; - let xy = AddXY{ x: 30, y: 70 }; + let x = Add10 { x: 90 }; + let z = Add20 { x: 80 }; + let a = Add30 { x: 70 }; + let xy = AddXY { x: 30, y: 70 }; assert_asd_eq_100(x); assert_asd_eq_100(z); assert_asd_eq_100(a); assert_asd_eq_100(xy); - assert(add_one_to_static_function(Static100{}) == 101); - assert(add_one_to_static_function(Static200{}) == 201); + assert(add_one_to_static_function(Static100 {}) == 101); + assert(add_one_to_static_function(Static200 {}) == 201); } diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/src/the_trait.nr b/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/src/the_trait.nr index d84210c4b44..c5cac4a1186 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/src/the_trait.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_where_clause/src/the_trait.nr @@ -6,4 +6,4 @@ trait StaticTrait { fn static_function(slf: Self) -> Field { 100 } -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/traits/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/traits/Nargo.toml index 75fb80c4bfa..a33e8681807 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/traits/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/traits/Nargo.toml @@ -2,6 +2,5 @@ name = "traits" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/traits/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/traits/src/main.nr index 2333c5da244..784ff01a883 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/traits/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/traits/src/main.nr @@ -16,6 +16,6 @@ impl Default for Foo { } fn main(x: Field, y: Field) { - let first = Foo::default(x,y); + let first = Foo::default(x, y); assert(first.bar == x); } diff --git a/tooling/nargo_cli/tests/compile_success_empty/unary_operators/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/unary_operators/Nargo.toml index 65ad7c1c70c..8ab6f708b8a 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/unary_operators/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/unary_operators/Nargo.toml @@ -2,6 +2,5 @@ name = "unary_operators" type = "bin" authors = [""] -compiler_version = "0.10.3" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/unary_operators/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/unary_operators/src/main.nr index 1c9145fd81f..ef622fd3eb9 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/unary_operators/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/unary_operators/src/main.nr @@ -4,4 +4,4 @@ fn main() { let y: i32 = -1; assert(x == 1 - 2); -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/unconstrained_empty/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/unconstrained_empty/Nargo.toml index a42660e8bb7..48d0f5938d8 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/unconstrained_empty/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/unconstrained_empty/Nargo.toml @@ -2,6 +2,4 @@ name = "unconstrained_empty" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/unconstrained_empty/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/unconstrained_empty/src/main.nr index 6a3e59c5fed..5e5fb297236 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/unconstrained_empty/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/unconstrained_empty/src/main.nr @@ -1,2 +1 @@ -unconstrained fn main() { -} +unconstrained fn main() {} diff --git a/tooling/nargo_cli/tests/compile_success_empty/unit/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/unit/Nargo.toml index 35fcd4bf339..7a15bd803c0 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/unit/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/unit/Nargo.toml @@ -2,6 +2,5 @@ name = "unit" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/unit/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/unit/src/main.nr index 2cb1f7d7c66..603829ec6db 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/unit/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/unit/src/main.nr @@ -9,6 +9,10 @@ fn main() { } fn f1() {} -fn f2() { () } +fn f2() { + () +} fn f3() -> () {} -fn f4() -> () { () } +fn f4() -> () { + () +} diff --git a/tooling/nargo_cli/tests/compile_success_empty/unused_variables/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/unused_variables/Nargo.toml index 61456b3a320..1447f07d81d 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/unused_variables/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/unused_variables/Nargo.toml @@ -2,6 +2,5 @@ name = "unused_variables" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/unused_variables/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/unused_variables/src/main.nr index d0ffa8a0d91..f82cace0509 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/unused_variables/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/unused_variables/src/main.nr @@ -1,3 +1 @@ -fn main(x : Field, y : pub Field) { - -} \ No newline at end of file +fn main(x: Field, y: pub Field) {} diff --git a/tooling/nargo_cli/tests/compile_success_empty/vectors/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/vectors/Nargo.toml index f628d5e27e1..e4c3889c685 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/vectors/Nargo.toml +++ b/tooling/nargo_cli/tests/compile_success_empty/vectors/Nargo.toml @@ -2,6 +2,5 @@ name = "vectors" type = "bin" authors = [""] -compiler_version = "0.7.1" [dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/Nargo.toml new file mode 100644 index 00000000000..ea2ffc0d2eb --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/Nargo.toml @@ -0,0 +1,7 @@ +[workspace] +members = [ + "library", + "library2", + "binary" +] +default-member = "binary" \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/binary/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/binary/Nargo.toml new file mode 100644 index 00000000000..90d8321589b --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/binary/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "binary" +type = "bin" +authors = [""] +[dependencies] +library = { path = "../library" } \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/binary/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/binary/src/main.nr new file mode 100644 index 00000000000..ab0ae9a48b8 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/binary/src/main.nr @@ -0,0 +1,2 @@ +use dep::library::ReExportMeFromAnotherLib; +fn main(_x: ReExportMeFromAnotherLib) {} diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library/Nargo.toml new file mode 100644 index 00000000000..88831bada4e --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "library" +type = "lib" +authors = [""] + +[dependencies] +library2 = { path = "../library2"} \ No newline at end of file diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library/src/lib.nr b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library/src/lib.nr new file mode 100644 index 00000000000..8e84662ed03 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library/src/lib.nr @@ -0,0 +1,2 @@ +// Re-export +use dep::library2::ReExportMeFromAnotherLib; diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library2/Nargo.toml b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library2/Nargo.toml new file mode 100644 index 00000000000..f2c20c0bf4a --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library2/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "library" +type = "lib" +authors = [""] +[dependencies] diff --git a/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library2/src/lib.nr b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library2/src/lib.nr new file mode 100644 index 00000000000..7e5a29a1424 --- /dev/null +++ b/tooling/nargo_cli/tests/compile_success_empty/workspace_reexport_bug/library2/src/lib.nr @@ -0,0 +1,5 @@ +// When we re-export this type from another library and then use it in +// main, we get a panic +struct ReExportMeFromAnotherLib { + x : Field, +} diff --git a/tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/Nargo.toml b/tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/Nargo.toml index 0ccf7ff8c9c..3adf969538c 100644 --- a/tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/Nargo.toml @@ -2,6 +2,4 @@ name = "1327_concrete_in_generic" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/src/main.nr b/tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/src/main.nr index 368d4811e45..e1d601b13c9 100644 --- a/tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/1327_concrete_in_generic/src/main.nr @@ -3,15 +3,13 @@ fn new_concrete_c_over_d() -> C { let d_method_interface = get_d_method_interface(); C::new(d_method_interface) } - // --- - - // Map - struct B { +// Map +struct B { new_concrete_t_c_constructor: fn()->T_C, } - impl B { +impl B { fn new(new_concrete_t_c_constructor: fn () -> T_C) -> B { B { new_concrete_t_c_constructor } } @@ -21,15 +19,13 @@ fn new_concrete_c_over_d() -> C { new_concrete_t_c_constructor() } } - // --- - - // Set - struct C { +// Set +struct C { t_d_interface: MethodInterface, } - impl C { +impl C { fn new (t_d_interface: MethodInterface) -> Self { C { t_d_interface } } @@ -39,17 +35,13 @@ fn new_concrete_c_over_d() -> C { some_method_on_t_d(t_d) } } - // --- - - struct MethodInterface { +struct MethodInterface { some_method_on_t_d: fn(T_D)->Field, } - // --- - - // Note - struct D { +// Note +struct D { d: Field, } @@ -58,11 +50,8 @@ fn d_method(input: D) -> Field { } fn get_d_method_interface() -> MethodInterface { - MethodInterface { - some_method_on_t_d: d_method, - } -} - + MethodInterface { some_method_on_t_d: d_method } +} // --- fn main(input: Field) -> pub Field { let b: B> = B::new(new_concrete_c_over_d); @@ -72,5 +61,4 @@ fn main(input: Field) -> pub Field { output } - // --- diff --git a/tooling/nargo_cli/tests/execution_success/1_mul/Nargo.toml b/tooling/nargo_cli/tests/execution_success/1_mul/Nargo.toml index 29053e36f7c..a0fd8d98027 100644 --- a/tooling/nargo_cli/tests/execution_success/1_mul/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/1_mul/Nargo.toml @@ -2,6 +2,5 @@ name = "1_mul" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/1_mul/src/main.nr b/tooling/nargo_cli/tests/execution_success/1_mul/src/main.nr index 4587b4b5947..8f4032dbd75 100644 --- a/tooling/nargo_cli/tests/execution_success/1_mul/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/1_mul/src/main.nr @@ -2,8 +2,8 @@ // The circuit should handle properly the growth of the bit size fn main(mut x: u32, y: u32, z: u32) { x *= y; - x *= x; //144 - x *= x; //20736 - x *= x; //429 981 696 + x *= x; //144 + x *= x; //20736 + x *= x; //429 981 696 assert(x == z); } diff --git a/tooling/nargo_cli/tests/execution_success/2_div/Nargo.toml b/tooling/nargo_cli/tests/execution_success/2_div/Nargo.toml index 6b28c58bea2..f689c97f760 100644 --- a/tooling/nargo_cli/tests/execution_success/2_div/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/2_div/Nargo.toml @@ -2,6 +2,5 @@ name = "2_div" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/2_div/src/main.nr b/tooling/nargo_cli/tests/execution_success/2_div/src/main.nr index ff0dee755cc..e16cc5be229 100644 --- a/tooling/nargo_cli/tests/execution_success/2_div/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/2_div/src/main.nr @@ -2,6 +2,6 @@ fn main(mut x: u32, y: u32, z: u32) { let a = x % y; assert(x / y == z); - assert(a == x - z*y); + assert(a == x - z * y); assert((50 as u64) % (9 as u64) == 5); } diff --git a/tooling/nargo_cli/tests/execution_success/3_add/Nargo.toml b/tooling/nargo_cli/tests/execution_success/3_add/Nargo.toml index dca0a0d9931..0bd2caef024 100644 --- a/tooling/nargo_cli/tests/execution_success/3_add/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/3_add/Nargo.toml @@ -2,6 +2,5 @@ name = "3_add" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/3_add/src/main.nr b/tooling/nargo_cli/tests/execution_success/3_add/src/main.nr index 2884415b81a..480348dc1cf 100644 --- a/tooling/nargo_cli/tests/execution_success/3_add/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/3_add/src/main.nr @@ -4,5 +4,5 @@ fn main(mut x: u32, y: u32, z: u32) { assert(x == z); x *= 8; - assert(x>9); + assert(x > 9); } diff --git a/tooling/nargo_cli/tests/execution_success/4_sub/Nargo.toml b/tooling/nargo_cli/tests/execution_success/4_sub/Nargo.toml index 149c3a6f7e5..b282bfe6287 100644 --- a/tooling/nargo_cli/tests/execution_success/4_sub/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/4_sub/Nargo.toml @@ -2,6 +2,5 @@ name = "4_sub" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/4_sub/src/main.nr b/tooling/nargo_cli/tests/execution_success/4_sub/src/main.nr index 60bcde9c0b3..6aef8e7b208 100644 --- a/tooling/nargo_cli/tests/execution_success/4_sub/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/4_sub/src/main.nr @@ -3,8 +3,4 @@ use dep::std; fn main(mut x: u32, y: u32, z: u32) { x = std::wrapping_sub(x,y); assert(x == z); - - // Test constant underflow (regression for #2045) - let x = -1 as u4; - assert(x == 15); } diff --git a/tooling/nargo_cli/tests/execution_success/5_over/Nargo.toml b/tooling/nargo_cli/tests/execution_success/5_over/Nargo.toml index a59347066c9..dd9a21b44bf 100644 --- a/tooling/nargo_cli/tests/execution_success/5_over/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/5_over/Nargo.toml @@ -2,6 +2,5 @@ name = "5_over" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/5_over/src/main.nr b/tooling/nargo_cli/tests/execution_success/5_over/src/main.nr index 42f339533aa..f24ff06cb2a 100644 --- a/tooling/nargo_cli/tests/execution_success/5_over/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/5_over/src/main.nr @@ -1,5 +1,4 @@ use dep::std; - // Test unsafe integer arithmetic // Test odd bits integer fn main(mut x: u32, y: u32) { diff --git a/tooling/nargo_cli/tests/execution_success/6/Nargo.toml b/tooling/nargo_cli/tests/execution_success/6/Nargo.toml index b0353fb6ae5..9774a5d8c47 100644 --- a/tooling/nargo_cli/tests/execution_success/6/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/6/Nargo.toml @@ -2,6 +2,5 @@ name = "6" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/6/src/main.nr b/tooling/nargo_cli/tests/execution_success/6/src/main.nr index 8b350de16c1..5ecb809e68b 100644 --- a/tooling/nargo_cli/tests/execution_success/6/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/6/src/main.nr @@ -3,7 +3,6 @@ // bytes. // // If you do not cast, it will take all the bytes from the field element! - // Mimc input is an array of field elements // The function is called mimc_bn254 to emphasize its parameters are chosen for bn254 curve, it should be used only with a proving system using the same curve (e.g Plonk from Aztec) use dep::std; @@ -14,7 +13,7 @@ fn main(x: [u8; 5], result: pub [u8; 32]) { digest = std::hash::sha256(x); assert(digest == result); - let y = [12,45,78,41]; - let h = std::hash::mimc_bn254(y); - assert(h == 18226366069841799622585958305961373004333097209608110160936134895615261821931); + let y = [12, 45, 78, 41]; + let h = std::hash::mimc::mimc_bn254(y); + assert(h == 18226366069841799622585958305961373004333097209608110160936134895615261821931); } diff --git a/tooling/nargo_cli/tests/execution_success/6_array/Nargo.toml b/tooling/nargo_cli/tests/execution_success/6_array/Nargo.toml index 4a6d8e1f401..c75df3e468e 100644 --- a/tooling/nargo_cli/tests/execution_success/6_array/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/6_array/Nargo.toml @@ -2,6 +2,5 @@ name = "6_array" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/6_array/src/main.nr b/tooling/nargo_cli/tests/execution_success/6_array/src/main.nr index 44a5363f8bc..6aa05f58b71 100644 --- a/tooling/nargo_cli/tests/execution_success/6_array/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/6_array/src/main.nr @@ -5,53 +5,47 @@ fn main(x: [u32; 5], y: [u32; 5], mut z: u32, t: u32) { z = y[4]; //Test 1: for i in 0..5 { - c = z*z*y[i]; - z -= c; + c = z*z*y[i]; + z -= c; } - assert(z == 0); //y[4]=0, so c and z are always 0 - + assert(z == 0); //y[4]=0, so c and z are always 0 //Test 2: c = 2301 as u32; for i in 0..5 { - c = t+2 as u32; - c = std::wrapping_mul(std::wrapping_mul(z,z),x[i]); - z =std::wrapping_add(z, std::wrapping_sub(x[i]*y[i] , c)); + c = t+2 as u32; + c = std::wrapping_mul(std::wrapping_mul(z,z),x[i]); + z =std::wrapping_add(z, std::wrapping_sub(x[i]*y[i] , c)); } assert(z == 3814912846); - //Test 3: c = 2300001 as u32; z = y[4]; for i in 0..5 { - z = z + x[i]*y[i]; + z = z + x[i]*y[i]; for _i in 0..3 { - c = i as u32 - 2 as u32; + c = std::wrapping_sub(i as u32,2 as u32); z = std::wrapping_mul(z,c); } } assert(z == 41472); - //Test 4: z = y[4]; for i in 0..3 { - z += x[i] * y[i]; - for j in 0..2 { - z += x[i+j] - y[i+j]; - } + z += x[i] * y[i]; + for j in 0..2 { + z += x[i+j] - y[i+j]; + } } assert(z == 11539); - //Test 5: let cc = if z < 1 { x } else { y }; assert(cc[0] == y[0]); - // Test 6: for-each loops for y_elem in y { for x_elem in x { assert(x_elem != y_elem); } } - // Test 7: Arrays of tuples/structs let mut tuple_array = [(1, 2), (3, 4), (5, 6)]; tuple_array[1] = (7, 8); diff --git a/tooling/nargo_cli/tests/execution_success/7/Nargo.toml b/tooling/nargo_cli/tests/execution_success/7/Nargo.toml index 9321253ec03..f69f89468d7 100644 --- a/tooling/nargo_cli/tests/execution_success/7/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/7/Nargo.toml @@ -2,6 +2,5 @@ name = "7" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/7_function/Nargo.toml b/tooling/nargo_cli/tests/execution_success/7_function/Nargo.toml index ea899378643..cec14ff7d6a 100644 --- a/tooling/nargo_cli/tests/execution_success/7_function/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/7_function/Nargo.toml @@ -2,6 +2,5 @@ name = "7_function" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/7_function/src/main.nr b/tooling/nargo_cli/tests/execution_success/7_function/src/main.nr index 8fd85fa31cf..95568dd4ccd 100644 --- a/tooling/nargo_cli/tests/execution_success/7_function/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/7_function/src/main.nr @@ -9,20 +9,18 @@ fn f2(mut x: Field) -> Field { x += 2; x } - // Simple example fn test0(mut a: Field) { a = f2(a); assert(a == 3); } - // Nested call fn test1(mut a: Field) { a = f1(a); assert(a == 4); } -fn test2(z: Field, t: u32 ) { +fn test2(z: Field, t: u32) { let a = z + t as Field; assert(a == 64); let e = pow(z, t as Field); @@ -49,7 +47,7 @@ fn test3(x: [u8; 3]) -> [u8; 3] { } fn test_multiple(x: u32, y: u32) -> (u32, u32) { - (y,x) + (y, x) } fn test_multiple2() -> my_struct { @@ -71,11 +69,11 @@ struct my2 { } fn test_multiple4(s: my_struct) { - assert(s.a == s.b+2); + assert(s.a == s.b + 2); } fn test_multiple5(a: (u32, u32)) { - assert(a.0 == a.1+2); + assert(a.0 == a.1 + 2); } fn test_multiple6(a: my2, b: my_struct, c: (my2, my_struct)) { @@ -92,21 +90,18 @@ fn bar() -> [Field; 1] { foo([0]) } -fn main(x: u32 , y: u32 , a: Field, arr1: [u32; 9], arr2: [u32; 9]) { - let mut ss: my_struct = my_struct { b: x, a: x+2, }; +fn main(x: u32, y: u32, a: Field, arr1: [u32; 9], arr2: [u32; 9]) { + let mut ss: my_struct = my_struct { b: x, a: x + 2 }; test_multiple4(ss); - test_multiple5((ss.a,ss.b)); - let my = my2 { - aa: ss, - bb: ss, - }; + test_multiple5((ss.a, ss.b)); + let my = my2 { aa: ss, bb: ss }; ss.a = 61; - test_multiple6(my, ss, (my,ss)); + test_multiple6(my, ss, (my, ss)); let my_block = { let mut ab = f2(a); ab = ab + a; - (x,ab) + (x, ab) }; assert(my_block.1 == 4); @@ -126,12 +121,10 @@ fn main(x: u32 , y: u32 , a: Field, arr1: [u32; 9], arr2: [u32; 9]) { let d = test_multiple2(); assert(d.b == d.a + 2 as u32); test_multiple3(y, y); - //Regression test for issue #628: let result = first(arr_to_field(arr1), arr_to_field(arr2)); assert(result[0] == arr1[0] as Field); } - // Issue #628 fn arr_to_field(arr: [u32; 9]) -> [Field; 9] { let mut as_field: [Field; 9] = [0 as Field; 9]; diff --git a/tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/Nargo.toml b/tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/Nargo.toml index 7bacc45d7d1..c9160aa2592 100644 --- a/tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/Nargo.toml @@ -2,6 +2,5 @@ name = "arithmetic_binary_operations" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/src/main.nr b/tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/src/main.nr index 8fb7bcdbeb2..69554f413a4 100644 --- a/tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/arithmetic_binary_operations/src/main.nr @@ -3,7 +3,7 @@ // The features being tested are: // Binary addition, multiplication, division, constant modulo // x = 3, y = 4, z = 5 -fn main(x : Field, y : Field, z : Field) -> pub Field { +fn main(x: Field, y: Field, z: Field) -> pub Field { //cast assert(y as u1 == 0); diff --git a/tooling/nargo_cli/tests/execution_success/array_dynamic/Nargo.toml b/tooling/nargo_cli/tests/execution_success/array_dynamic/Nargo.toml index 17b38706704..25684b00377 100644 --- a/tooling/nargo_cli/tests/execution_success/array_dynamic/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/array_dynamic/Nargo.toml @@ -2,6 +2,5 @@ name = "array_dynamic" type = "bin" authors = [""] -compiler_version = "0.1" [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 index 14b6f7d3b85..9e21334e510 100644 --- a/tooling/nargo_cli/tests/execution_success/array_dynamic/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/array_dynamic/src/main.nr @@ -1,18 +1,17 @@ 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; + let idx = (z - 5 * t - 5) as Field; //dynamic array test - dyn_array(x, idx, idx - 3); - + dyn_array(x, idx, idx - 3); //regression for issue 1283 let mut s = 0; - let x3 = [246,159,32,176,8]; + let x3 = [246, 159, 32, 176, 8]; for i in 0..5 { - s += x3[index[i]]; + s += x3[index[i]]; } - assert(s!=0); + assert(s != 0); if 3 < (sublen as u32) { - assert(index[offset + 3] == index2[3]); + assert(index[offset + 3] == index2[3]); } } @@ -23,9 +22,9 @@ fn dyn_array(mut x: [u32; 5], y: Field, z: Field) { assert(x[y] == 111); assert(x[1] == 0); if y as u32 < 10 { - x[y] = x[y] - 2; + x[y] = x[y] - 2; } else { - x[y] = 0; + x[y] = 0; } assert(x[4] == 109); } diff --git a/tooling/nargo_cli/tests/execution_success/array_eq/Nargo.toml b/tooling/nargo_cli/tests/execution_success/array_eq/Nargo.toml index 4a9bd6293c0..1020d4905b1 100644 --- a/tooling/nargo_cli/tests/execution_success/array_eq/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/array_eq/Nargo.toml @@ -2,6 +2,5 @@ name = "array_eq" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/array_eq/src/main.nr b/tooling/nargo_cli/tests/execution_success/array_eq/src/main.nr index d1771ed91a6..5bbd595898c 100644 --- a/tooling/nargo_cli/tests/execution_success/array_eq/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/array_eq/src/main.nr @@ -1,4 +1,4 @@ // Simple example of checking where two arrays are equal fn main(a: [Field; 32], b: [Field; 32]) { - assert(a == b); + assert(a == b); } diff --git a/tooling/nargo_cli/tests/execution_success/array_len/Nargo.toml b/tooling/nargo_cli/tests/execution_success/array_len/Nargo.toml index b54cea7cc17..24ac6ff7f13 100644 --- a/tooling/nargo_cli/tests/execution_success/array_len/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/array_len/Nargo.toml @@ -2,6 +2,5 @@ name = "array_len" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/array_len/src/main.nr b/tooling/nargo_cli/tests/execution_success/array_len/src/main.nr index 3e9d3603311..b60762f4636 100644 --- a/tooling/nargo_cli/tests/execution_success/array_len/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/array_len/src/main.nr @@ -15,10 +15,8 @@ fn main(x: Field, len3: [u8; 3], len4: [Field; 4]) { assert(len_plus_1(len4) == 5); assert(add_lens(len3, len4) == 7); assert(nested_call(len4) == 5); - // std::array::len returns a compile-time known value assert(len4[len3.len()] == 4); - // Regression for #1023, ensure .len still works after calling to_le_bytes on a witness. // This was needed because normally .len is evaluated before acir-gen where to_le_bytes // on a witness is only evaluated during/after acir-gen. diff --git a/tooling/nargo_cli/tests/execution_success/array_neq/Nargo.toml b/tooling/nargo_cli/tests/execution_success/array_neq/Nargo.toml index 0539cceb542..2e4bbdf97ee 100644 --- a/tooling/nargo_cli/tests/execution_success/array_neq/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/array_neq/Nargo.toml @@ -2,6 +2,5 @@ name = "array_neq" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/array_neq/src/main.nr b/tooling/nargo_cli/tests/execution_success/array_neq/src/main.nr index be734dea368..a3e51dc5066 100644 --- a/tooling/nargo_cli/tests/execution_success/array_neq/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/array_neq/src/main.nr @@ -1,4 +1,4 @@ // Simple example of checking where two arrays are different fn main(a: [Field; 32], b: [Field; 32]) { - assert(a != b); + assert(a != b); } diff --git a/tooling/nargo_cli/tests/execution_success/array_sort/Nargo.toml b/tooling/nargo_cli/tests/execution_success/array_sort/Nargo.toml index f5f469c5a5f..28e9c65a0dc 100644 --- a/tooling/nargo_cli/tests/execution_success/array_sort/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/array_sort/Nargo.toml @@ -2,6 +2,4 @@ name = "array_sort" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/array_sort/src/main.nr b/tooling/nargo_cli/tests/execution_success/array_sort/src/main.nr index 17df7b23551..4f40a2cee84 100644 --- a/tooling/nargo_cli/tests/execution_success/array_sort/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/array_sort/src/main.nr @@ -1,4 +1,4 @@ -fn main(xs : [u8; 3]) { +fn main(xs: [u8; 3]) { let sorted = xs.sort(); assert(sorted[0] == 1); assert(sorted[1] == 2); diff --git a/tooling/nargo_cli/tests/execution_success/assert/Nargo.toml b/tooling/nargo_cli/tests/execution_success/assert/Nargo.toml index 17ed9362bef..7780d53459e 100644 --- a/tooling/nargo_cli/tests/execution_success/assert/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/assert/Nargo.toml @@ -2,6 +2,5 @@ name = "assert" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/assert_statement/Nargo.toml b/tooling/nargo_cli/tests/execution_success/assert_statement/Nargo.toml index 641cb1b00e0..c6a1daaed19 100644 --- a/tooling/nargo_cli/tests/execution_success/assert_statement/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/assert_statement/Nargo.toml @@ -2,6 +2,5 @@ name = "assert_statement" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/assert_statement/src/main.nr b/tooling/nargo_cli/tests/execution_success/assert_statement/src/main.nr index f9359ded812..2646a0b85c2 100644 --- a/tooling/nargo_cli/tests/execution_success/assert_statement/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/assert_statement/src/main.nr @@ -1,7 +1,7 @@ // Tests a very simple program. // // The features being tested is assertion -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { assert(x == y, "x and y are not equal"); assert_eq(x, y, "x and y are not equal"); } diff --git a/tooling/nargo_cli/tests/execution_success/assign_ex/Nargo.toml b/tooling/nargo_cli/tests/execution_success/assign_ex/Nargo.toml index 2ca969eeb93..4ef7b3aa5a6 100644 --- a/tooling/nargo_cli/tests/execution_success/assign_ex/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/assign_ex/Nargo.toml @@ -2,6 +2,5 @@ name = "assign_ex" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/assign_ex/src/main.nr b/tooling/nargo_cli/tests/execution_success/assign_ex/src/main.nr index 75cd841a301..b5cfc162cc4 100644 --- a/tooling/nargo_cli/tests/execution_success/assign_ex/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/assign_ex/src/main.nr @@ -6,7 +6,6 @@ fn main(x: Field, y: Field) { regression_3057(); } - // Ensure parsing parenthesized lvalues works fn regression_3057() { let mut array = [[0, 1], [2, 3]]; diff --git a/tooling/nargo_cli/tests/execution_success/bit_and/Nargo.toml b/tooling/nargo_cli/tests/execution_success/bit_and/Nargo.toml index 71a98db6635..e9a28577079 100644 --- a/tooling/nargo_cli/tests/execution_success/bit_and/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/bit_and/Nargo.toml @@ -2,6 +2,5 @@ name = "bit_and" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/bit_and/src/main.nr b/tooling/nargo_cli/tests/execution_success/bit_and/src/main.nr index 35671abea63..0bc1d9a49bd 100644 --- a/tooling/nargo_cli/tests/execution_success/bit_and/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/bit_and/src/main.nr @@ -1,15 +1,13 @@ // You can only do bit operations with integers. // (Kobi/Daira/Circom/#37) https://github.com/iden3/circom/issues/37 -fn main(x : Field, y : Field) { +fn main(x: Field, y: Field) { let x_as_u8 = x as u8; let y_as_u8 = y as u8; - - assert((x_as_u8 & y_as_u8) == x_as_u8); + assert((x_as_u8 & y_as_u8) == x_as_u8); //bitwise and with 1 bit: let flag = (x == 0) & (y == 16); assert(flag); - //bitwise and with odd bits: let x_as_u11 = x as u11; let y_as_u11 = y as u11; diff --git a/tooling/nargo_cli/tests/execution_success/bit_shifts_comptime/Nargo.toml b/tooling/nargo_cli/tests/execution_success/bit_shifts_comptime/Nargo.toml index 9b7aa319406..81272be4e98 100644 --- a/tooling/nargo_cli/tests/execution_success/bit_shifts_comptime/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/bit_shifts_comptime/Nargo.toml @@ -2,6 +2,5 @@ name = "bit_shifts_comptime" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] 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 index 209861e74fa..8afed4c1e1e 100644 --- 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 @@ -1,23 +1,21 @@ 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); + // 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); + assert(a == 0); let b: u32 = 1 >> 32; - assert(b == 0); + assert(b == 0); } diff --git a/tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/Nargo.toml b/tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/Nargo.toml index 3f9058f1946..f60c7dbe658 100644 --- a/tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/Nargo.toml @@ -2,6 +2,5 @@ name = "bit_shifts_runtime" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/src/main.nr b/tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/src/main.nr index f4d9c3916a6..a2c873a7e7f 100644 --- a/tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/bit_shifts_runtime/src/main.nr @@ -1,9 +1,8 @@ fn main(x: u64, y: u64) { - // runtime shifts on compile-time known values - assert(64 << y == 128); - assert(64 >> y == 32); - - // runtime shifts on runtime values - assert(x << y == 128); - assert(x >> y == 32); + // runtime shifts on compile-time known values + assert(64 << y == 128); + assert(64 >> y == 32); + // runtime shifts on runtime values + assert(x << y == 128); + assert(x >> y == 32); } diff --git a/tooling/nargo_cli/tests/execution_success/bool_not/Nargo.toml b/tooling/nargo_cli/tests/execution_success/bool_not/Nargo.toml index c2521450344..fe42e1efa11 100644 --- a/tooling/nargo_cli/tests/execution_success/bool_not/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/bool_not/Nargo.toml @@ -2,6 +2,5 @@ name = "bool_not" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/bool_or/Nargo.toml b/tooling/nargo_cli/tests/execution_success/bool_or/Nargo.toml index a878c1acb38..e139a7a2947 100644 --- a/tooling/nargo_cli/tests/execution_success/bool_or/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/bool_or/Nargo.toml @@ -2,6 +2,5 @@ name = "bool_or" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/Nargo.toml index 42b3c71aad3..aef4fd56d4f 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_acir_as_brillig" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/src/main.nr index da5982dcd04..5bd6ce0adb2 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_acir_as_brillig/src/main.nr @@ -4,15 +4,15 @@ fn main(x: u32) { assert(deep_entry_point(x) == 4); } -fn inner(x : u32) -> u32 { +fn inner(x: u32) -> u32 { x + 1 } -unconstrained fn entry_point(x : u32) -> u32 { +unconstrained fn entry_point(x: u32) -> u32 { inner(x + 1) } -fn swap(x: u32, y:u32) -> (u32, u32) { +fn swap(x: u32, y: u32) -> (u32, u32) { (y, x) } @@ -25,18 +25,18 @@ unconstrained fn swap_entry_point(x: u32, y: u32) { assert(swapped_twice.1 == y); } -fn level_3(x : u32) -> u32 { +fn level_3(x: u32) -> u32 { x + 1 } -fn level_2(x : u32) -> u32 { +fn level_2(x: u32) -> u32 { level_3(x + 1) } -fn level_1(x : u32) -> u32 { +fn level_1(x: u32) -> u32 { level_2(x + 1) } -unconstrained fn deep_entry_point(x : u32) -> u32 { +unconstrained fn deep_entry_point(x: u32) -> u32 { level_1(x + 1) } diff --git a/tooling/nargo_cli/tests/execution_success/brillig_arrays/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_arrays/Nargo.toml index abaa6680f84..a4433e380a9 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_arrays/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_arrays/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_arrays" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_assert/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_assert/Nargo.toml index c6a27b47e79..b7d9231ab75 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_assert/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_assert/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_assert" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_assert/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_assert/src/main.nr index d17c0b4f991..91e4cebd9d3 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_assert/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_assert/src/main.nr @@ -5,7 +5,7 @@ fn main(x: Field) { assert(1 == conditional(x as bool)); } -unconstrained fn conditional(x : bool) -> Field { +unconstrained fn conditional(x: bool) -> Field { assert(x, "x is false"); assert_eq(x, true, "x is false"); 1 diff --git a/tooling/nargo_cli/tests/execution_success/brillig_blake2s/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_blake2s/Nargo.toml index 8fc7df96fc3..a497b6f48cc 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_blake2s/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_blake2s/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_blake2s" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_blake2s/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_blake2s/src/main.nr index df20b6a9ce1..5bd52666ae9 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_blake2s/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_blake2s/src/main.nr @@ -1,5 +1,4 @@ use dep::std; - // Tests a very simple program. // // The features being tested is blake2s in brillig diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_calls/Nargo.toml index 9b6b4bd357b..7cc53a33a8a 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_calls/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_calls/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_calls" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_calls/src/main.nr index 656d241d2f5..5c39713f5bb 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_calls/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_calls/src/main.nr @@ -8,7 +8,7 @@ fn main(x: u32) { multiple_values_entry_point(x); } -unconstrained fn returns_multiple_values(x : u32) -> (u32, u32, u32, u32) { +unconstrained fn returns_multiple_values(x: u32) -> (u32, u32, u32, u32) { (x + 1, x + 2, x + 3, x + 4) } @@ -20,15 +20,15 @@ unconstrained fn multiple_values_entry_point(x: u32) { assert(d == x + 4); } -unconstrained fn inner(x : u32) -> u32 { +unconstrained fn inner(x: u32) -> u32 { x + 1 } -unconstrained fn entry_point(x : u32) -> u32 { +unconstrained fn entry_point(x: u32) -> u32 { inner(x + 1) } -unconstrained fn swap(x: u32, y:u32) -> (u32, u32) { +unconstrained fn swap(x: u32, y: u32) -> (u32, u32) { (y, x) } @@ -41,18 +41,18 @@ unconstrained fn swap_entry_point(x: u32, y: u32) { assert(swapped_twice.1 == y); } -unconstrained fn level_3(x : u32) -> u32 { +unconstrained fn level_3(x: u32) -> u32 { x + 1 } -unconstrained fn level_2(x : u32) -> u32 { +unconstrained fn level_2(x: u32) -> u32 { level_3(x + 1) } -unconstrained fn level_1(x : u32) -> u32 { +unconstrained fn level_1(x: u32) -> u32 { level_2(x + 1) } -unconstrained fn deep_entry_point(x : u32) -> u32 { +unconstrained fn deep_entry_point(x: u32) -> u32 { level_1(x + 1) } diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls_array/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_calls_array/Nargo.toml index 0c60f6218eb..e360f2d6338 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_calls_array/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_calls_array/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_calls_array" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls_array/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_calls_array/src/main.nr index d5702ac4f82..1b1d89f6366 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_calls_array/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_calls_array/src/main.nr @@ -6,11 +6,11 @@ fn main(x: [u32; 3]) { another_entry_point(x); } -unconstrained fn inner(x : [u32; 3]) -> [u32; 3] { +unconstrained fn inner(x: [u32; 3]) -> [u32; 3] { [x[0] + 1, x[1] + 1, x[2] + 1] } -unconstrained fn entry_point(x : [u32; 3]) -> u32 { +unconstrained fn entry_point(x: [u32; 3]) -> u32 { let y = inner(x); y[0] + y[1] + y[2] } diff --git a/tooling/nargo_cli/tests/execution_success/brillig_calls_conditionals/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_calls_conditionals/Nargo.toml index f99445381d3..1553cd525ff 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_calls_conditionals/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_calls_conditionals/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_calls_conditionals" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_conditional/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_conditional/Nargo.toml index 7432f303349..6a8be620fee 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_conditional/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_conditional/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_conditional" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_conditional/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_conditional/src/main.nr index a3d92ab58e9..a59336a877b 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_conditional/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_conditional/src/main.nr @@ -5,10 +5,6 @@ fn main(x: Field) { assert(4 == conditional(x == 1)); } -unconstrained fn conditional(x : bool) -> Field { - if x { - 4 - }else { - 5 - } +unconstrained fn conditional(x: bool) -> Field { + if x { 4 } else { 5 } } diff --git a/tooling/nargo_cli/tests/execution_success/brillig_ecdsa/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_ecdsa/Nargo.toml index 96ffe8f1c92..972dd9ce93b 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_ecdsa/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_ecdsa/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_ecdsa" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_ecdsa/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_ecdsa/src/main.nr index 9b4627adf40..23f017aa336 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_ecdsa/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_ecdsa/src/main.nr @@ -1,12 +1,11 @@ use dep::std; - // Tests a very simple program. // // The features being tested is ecdsa in brillig -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { +fn main(hashed_message: [u8;32], pub_key_x: [u8;32], pub_key_y: [u8;32], signature: [u8;64]) { assert(ecdsa(hashed_message, pub_key_x, pub_key_y, signature)); } -unconstrained fn ecdsa(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) -> bool { +unconstrained fn ecdsa(hashed_message: [u8;32], pub_key_x: [u8;32], pub_key_y: [u8;32], signature: [u8;64]) -> bool { std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message) } diff --git a/tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/Nargo.toml index fd94bfb3a60..decd9a9412a 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_fns_as_values" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/src/main.nr index 5f8435825f6..2f5d14583d5 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_fns_as_values/src/main.nr @@ -1,3 +1,5 @@ +use dep::std; + struct MyStruct { operation: fn (u32) -> u32, } @@ -5,9 +7,9 @@ struct MyStruct { fn main(x: u32) { assert(wrapper(increment, x) == x + 1); assert(wrapper(increment_acir, x) == x + 1); - assert(wrapper(decrement, x) == x - 1); + assert(wrapper(decrement, x) == std::wrapping_sub(x, 1)); assert(wrapper_with_struct(MyStruct { operation: increment }, x) == x + 1); - assert(wrapper_with_struct(MyStruct { operation: decrement }, x) == x - 1); + assert(wrapper_with_struct(MyStruct { operation: decrement }, x) == std::wrapping_sub(x, 1)); // https://github.com/noir-lang/noir/issues/1975 assert(increment(x) == x + 1); } diff --git a/tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/Nargo.toml index a7d75459f7e..7cfcc745f0d 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_hash_to_field" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/src/main.nr index ee743c19ee5..4b4177a521e 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_hash_to_field/src/main.nr @@ -1,5 +1,4 @@ use dep::std; - // Tests a very simple program. // // The features being tested is hash_to_field in brillig @@ -7,6 +6,6 @@ fn main(input: Field) -> pub Field { hash_to_field(input) } -unconstrained fn hash_to_field(input : Field) -> Field { +unconstrained fn hash_to_field(input: Field) -> Field { std::hash::hash_to_field([input]) } diff --git a/tooling/nargo_cli/tests/execution_success/brillig_identity_function/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_identity_function/Nargo.toml index 1c7603a5660..8196884fe2b 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_identity_function/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_identity_function/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_identity_function" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_identity_function/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_identity_function/src/main.nr index ca646140f21..f41188b1f0d 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_identity_function/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_identity_function/src/main.nr @@ -2,11 +2,10 @@ struct myStruct { foo: Field, foo_arr: [Field; 2], } - // Tests a very simple program. // // The features being tested is the identity function in Brillig -fn main(x : Field) { +fn main(x: Field) { assert(x == identity(x)); // TODO: add support for array comparison let arr = identity_array([x, x]); @@ -20,14 +19,14 @@ fn main(x : Field) { assert(x == identity_struct.foo_arr[1]); } -unconstrained fn identity(x : Field) -> Field { +unconstrained fn identity(x: Field) -> Field { x } -unconstrained fn identity_array(arr : [Field; 2]) -> [Field; 2] { +unconstrained fn identity_array(arr: [Field; 2]) -> [Field; 2] { arr } -unconstrained fn identity_struct(s : myStruct) -> myStruct { +unconstrained fn identity_struct(s: myStruct) -> myStruct { s } diff --git a/tooling/nargo_cli/tests/execution_success/brillig_keccak/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_keccak/Nargo.toml index 358c7c63a60..8cacf2186b8 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_keccak/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_keccak/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_keccak" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_keccak/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_keccak/src/main.nr index 46c2a59f6b6..1e9b65a6eb4 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_keccak/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_keccak/src/main.nr @@ -1,5 +1,4 @@ use dep::std; - // Tests a very simple program. // // The features being tested is keccak256 in brillig @@ -8,16 +7,15 @@ fn main(x: Field, result: [u8; 32]) { // The padding is taken care of by the program let digest = keccak256([x as u8], 1); assert(digest == result); - //#1399: variable meesage size let message_size = 4; - let hash_a = keccak256([1,2,3,4], message_size); - let hash_b = keccak256([1,2,3,4,0,0,0,0], message_size); + let hash_a = keccak256([1, 2, 3, 4], message_size); + let hash_b = keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); assert(hash_a == hash_b); let message_size_big = 8; - let hash_c = keccak256([1,2,3,4,0,0,0,0], message_size_big); + let hash_c = keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); assert(hash_a != hash_c); } diff --git a/tooling/nargo_cli/tests/execution_success/brillig_loop/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_loop/Nargo.toml index c43a806784a..1212397c4db 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_loop/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_loop/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_loop" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/Nargo.toml index 4ce5518efb5..c36c8a0a2bd 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/Nargo.toml @@ -2,6 +2,4 @@ name = "brillig_nested_arrays" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/src/main.nr index e182585f5e5..d0a60ac0a58 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_nested_arrays/src/main.nr @@ -13,16 +13,16 @@ unconstrained fn access_nested(notes: [MyNote; 2], x: Field, y: Field) -> Field } unconstrained fn create_inside_brillig(x: Field, y: Field) { - let header = Header { params: [1, 2, 3]}; - let note0 = MyNote { array: [1, 2], plain : 3, header }; - let note1 = MyNote { array: [4, 5], plain : 6, header }; + let header = Header { params: [1, 2, 3] }; + let note0 = MyNote { array: [1, 2], plain: 3, header }; + let note1 = MyNote { array: [4, 5], plain: 6, header }; assert(access_nested([note0, note1], x, y) == (2 + 4 + 3 + 1)); } fn main(x: Field, y: Field) { - let header = Header { params: [1, 2, 3]}; - let note0 = MyNote { array: [1, 2], plain : 3, header }; - let note1 = MyNote { array: [4, 5], plain : 6, header }; + let header = Header { params: [1, 2, 3] }; + let note0 = MyNote { array: [1, 2], plain: 3, header }; + let note1 = MyNote { array: [4, 5], plain: 6, header }; create_inside_brillig(x, y); assert(access_nested([note0, note1], x, y) == (2 + 4 + 3 + 1)); diff --git a/tooling/nargo_cli/tests/execution_success/brillig_nested_slices/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_nested_slices/Nargo.toml index 3a558b737d8..d84338cdbb4 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_nested_slices/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_nested_slices/Nargo.toml @@ -2,6 +2,4 @@ name = "brillig_nested_slices" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_not/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_not/Nargo.toml index 38a0872adfb..ef882ea8da0 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_not/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_not/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_not" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_not/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_not/src/main.nr index 34ed2199902..d34b3edb4b6 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_not/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_not/src/main.nr @@ -1,11 +1,11 @@ // Tests a very simple Brillig function. // // The features being tested is not instruction on brillig -fn main(x: Field, y : Field) { +fn main(x: Field, y: Field) { assert(false == not_operator(x as bool)); assert(true == not_operator(y as bool)); } -unconstrained fn not_operator(x : bool) -> bool { +unconstrained fn not_operator(x: bool) -> bool { !x } diff --git a/tooling/nargo_cli/tests/execution_success/brillig_oracle/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_oracle/Nargo.toml index 0b03be79ef8..13bd913cef7 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_oracle/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_oracle/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_oracle" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] 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 index ece23996a65..86cf6ff1498 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_oracle/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_oracle/src/main.nr @@ -1,15 +1,12 @@ 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] {} diff --git a/tooling/nargo_cli/tests/execution_success/brillig_pedersen/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_pedersen/Nargo.toml index f6f34dcc650..6327caa0a09 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_pedersen/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_pedersen/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_pedersen" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_pedersen/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_pedersen/src/main.nr index dfa10c96663..2379818c454 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_pedersen/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_pedersen/src/main.nr @@ -1,21 +1,22 @@ use dep::std; unconstrained fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: Field) { - let res = std::hash::pedersen_with_separator([x, y], 0); - assert(res[0] == out_x); - assert(res[1] == out_y); + let res = std::hash::pedersen_commitment_with_separator([x, y], 0); + assert(res.x == out_x); + assert(res.y == out_y); + let res_hash = std::hash::pedersen_hash_with_separator([x, y], 0); assert_eq(res_hash, out_hash); - assert(res_hash != res[0]); + assert(res_hash != res.x); - let raw_data = [x,y]; + let raw_data = [x, y]; let mut state = 0; for i in 0..(2 as u32) { state = state * 8 + raw_data[i]; } state += salt; - let hash = std::hash::pedersen_with_separator([state], 0); - assert(std::hash::pedersen_with_separator([43], 0)[0] == hash[0]); + let hash = std::hash::pedersen_commitment_with_separator([state], 0); + assert(std::hash::pedersen_commitment_with_separator([43], 0).x == hash.x); } diff --git a/tooling/nargo_cli/tests/execution_success/brillig_recursion/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_recursion/Nargo.toml index 32dd1a6c858..087eeefd5ac 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_recursion/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_recursion/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_recursion" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_recursion/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_recursion/src/main.nr index 43d1034fbbf..a87ef28bc56 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_recursion/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_recursion/src/main.nr @@ -5,7 +5,7 @@ fn main(x: u32) { assert(fibonacci(x) == 55); } -unconstrained fn fibonacci(x : u32) -> u32 { +unconstrained fn fibonacci(x: u32) -> u32 { if x <= 1 { x } else { diff --git a/tooling/nargo_cli/tests/execution_success/brillig_references/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_references/Nargo.toml index 7f47fab9d9a..0f64b862ba0 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_references/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_references/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_references" type = "bin" authors = [""] -compiler_version = "0.5.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_references/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_references/src/main.nr index 46372940bc8..e1f906beb0a 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_references/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_references/src/main.nr @@ -1,29 +1,20 @@ unconstrained fn main(mut x: Field) { add1(&mut x); assert(x == 3); - // https://github.com/noir-lang/noir/issues/1899 // let mut s = S { y: x }; // s.add2(); // assert(s.y == 5); - // Test that normal mutable variables are still copied let mut a = 0; mutate_copy(a); assert(a == 0); - // Test something 3 allocations deep let mut nested_allocations = Nested { y: &mut &mut 0 }; add1(*nested_allocations.y); assert(**nested_allocations.y == 1); - // Test nested struct allocations with a mutable reference to an array. - let mut c = C { - foo: 0, - bar: &mut C2 { - array: &mut [1, 2], - }, - }; + let mut c = C { foo: 0, bar: &mut C2 { array: &mut [1, 2] } }; *c.bar.array = [3, 4]; let arr: [Field; 2] = *c.bar.array; assert(arr[0] == 3); diff --git a/tooling/nargo_cli/tests/execution_success/brillig_scalar_mul/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_scalar_mul/Nargo.toml index a580584f7f9..eefd041b899 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_scalar_mul/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_scalar_mul/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_scalar_mul" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] 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 index b95a8d4ef4a..30c51ce0f50 100644 --- 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 @@ -1,22 +1,16 @@ 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 -) { +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; - } + 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); + assert(res[0] == pub_x); + assert(res[1] == pub_y); } diff --git a/tooling/nargo_cli/tests/execution_success/brillig_schnorr/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_schnorr/Nargo.toml index 3defa68f561..1b598abbf74 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_schnorr/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_schnorr/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_schnorr" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] 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 index 4212839601f..107b311f6ab 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_schnorr/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_schnorr/src/main.nr @@ -1,5 +1,4 @@ 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]) { @@ -12,10 +11,9 @@ unconstrained fn main(message: [u8; 10], message_field: Field, pub_key_x: Field, // 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); + 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); + 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/brillig_sha256/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_sha256/Nargo.toml index 6aebe1ed5ad..7140fa0fd0b 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_sha256/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_sha256/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_sha256" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_sha256/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_sha256/src/main.nr index 077ff70048e..e76109df9c3 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_sha256/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_sha256/src/main.nr @@ -1,5 +1,4 @@ use dep::std; - // Tests a very simple program. // // The features being tested is sha256 in brillig diff --git a/tooling/nargo_cli/tests/execution_success/brillig_slices/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_slices/Nargo.toml index 51d81efb6ae..5f6caad088a 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_slices/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_slices/Nargo.toml @@ -2,6 +2,4 @@ name = "brillig_slices" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_slices/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_slices/src/main.nr index 403956bc23d..48bc8a76bb8 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_slices/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_slices/src/main.nr @@ -8,7 +8,6 @@ unconstrained fn main(x: Field, y: Field) { assert(slice[0] == y); assert(slice[1] == x); assert(slice[2] == 7); - // Array set on slice target slice[0] = x; slice[1] = y; @@ -69,12 +68,10 @@ unconstrained fn main(x: Field, y: Field) { regression_merge_slices(x, y); } - // Tests slice passing to/from functions unconstrained fn push_front_to_slice(slice: [T], item: T) -> [T] { slice.push_front(item) } - // The parameters to this function must come from witness values (inputs to main) unconstrained fn regression_merge_slices(x: Field, y: Field) { merge_slices_if(x, y); @@ -109,21 +106,15 @@ unconstrained fn merge_slices_else(x: Field) { assert(slice[2] == 5); assert(slice.len() == 3); } - // Test returning a merged slice without a mutation unconstrained fn merge_slices_return(x: Field, y: Field) -> [Field] { let slice = [0; 2]; if x != y { - if x != 20 { - slice.push_back(y) - } else { - slice - } + if x != 20 { slice.push_back(y) } else { slice } } else { slice } } - // Test mutating a slice inside of an if statement unconstrained fn merge_slices_mutate(x: Field, y: Field) -> [Field] { let mut slice = [0; 2]; @@ -135,7 +126,6 @@ unconstrained fn merge_slices_mutate(x: Field, y: Field) -> [Field] { } slice } - // Test mutating a slice inside of a loop in an if statement unconstrained fn merge_slices_mutate_in_loop(x: Field, y: Field) -> [Field] { let mut slice = [0; 2]; diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/Nargo.toml index 21c5104e6a8..df6c818c90f 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_to_be_bytes" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/src/main.nr index d1e1cb9c9a5..9d78411f060 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_to_be_bytes/src/main.nr @@ -1,4 +1,4 @@ -unconstrained fn main(x : Field) -> pub [u8; 31] { +unconstrained fn main(x: Field) -> pub [u8; 31] { // The result of this byte array will be big-endian let byte_array = x.to_be_bytes(31); let mut bytes = [0; 31]; diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/Nargo.toml index 10c2abeee29..991f3d1e46c 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_to_bytes_integration" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/src/main.nr index 775d1e512d9..e8e5b9db9ca 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_to_bytes_integration/src/main.nr @@ -1,12 +1,12 @@ use dep::std; -unconstrained fn main(x : Field, _y: Field) { +unconstrained fn main(x: Field, _y: Field) { // The result of this byte array will be big-endian let y: Field = 2040124; let be_byte_array = y.to_be_bytes(31); // The result of this byte array will be little-endian let le_byte_array = x.to_le_bytes(31); - + assert(le_byte_array[0] == 60); assert(le_byte_array[0] == be_byte_array[30]); assert(le_byte_array[1] == be_byte_array[29]); diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/Nargo.toml index e1ba633bff1..c2ce8ad01b5 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_to_le_bytes" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/src/main.nr b/tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/src/main.nr index 1b1315ea411..77d292cf01b 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/brillig_to_le_bytes/src/main.nr @@ -1,4 +1,4 @@ -unconstrained fn main(x : Field) -> pub [u8; 31] { +unconstrained fn main(x: Field) -> pub [u8; 31] { // The result of this byte array will be little-endian let byte_array = x.to_le_bytes(31); assert(byte_array.len() == 31); diff --git a/tooling/nargo_cli/tests/execution_success/brillig_top_level/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_top_level/Nargo.toml index 79686cab2ea..f74a2a82964 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_top_level/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_top_level/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_top_level" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/brillig_unitialised_arrays/Nargo.toml b/tooling/nargo_cli/tests/execution_success/brillig_unitialised_arrays/Nargo.toml index c7045d0b816..f23ecc787d0 100644 --- a/tooling/nargo_cli/tests/execution_success/brillig_unitialised_arrays/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/brillig_unitialised_arrays/Nargo.toml @@ -2,6 +2,5 @@ name = "brillig_unitialised_arrays" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/cast_bool/Nargo.toml b/tooling/nargo_cli/tests/execution_success/cast_bool/Nargo.toml index 65a878d776a..6571019494e 100644 --- a/tooling/nargo_cli/tests/execution_success/cast_bool/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/cast_bool/Nargo.toml @@ -2,6 +2,5 @@ name = "cast_bool" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/closures_mut_ref/Nargo.toml b/tooling/nargo_cli/tests/execution_success/closures_mut_ref/Nargo.toml index f70cde6f878..01936c7be65 100644 --- a/tooling/nargo_cli/tests/execution_success/closures_mut_ref/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/closures_mut_ref/Nargo.toml @@ -2,6 +2,4 @@ name = "closures_mut_ref" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/closures_mut_ref/src/main.nr b/tooling/nargo_cli/tests/execution_success/closures_mut_ref/src/main.nr index 99de3dd31e4..5a743d1b633 100644 --- a/tooling/nargo_cli/tests/execution_success/closures_mut_ref/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/closures_mut_ref/src/main.nr @@ -17,7 +17,6 @@ fn main(mut x: Field) { issue_2120(); } - // https://github.com/noir-lang/noir/issues/2120 fn issue_2120() { let x1 = &mut 42; diff --git a/tooling/nargo_cli/tests/execution_success/conditional_1/Nargo.toml b/tooling/nargo_cli/tests/execution_success/conditional_1/Nargo.toml index af1efa03e82..28ca01332df 100644 --- a/tooling/nargo_cli/tests/execution_success/conditional_1/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/conditional_1/Nargo.toml @@ -2,6 +2,5 @@ name = "conditional_1" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/conditional_1/src/main.nr b/tooling/nargo_cli/tests/execution_success/conditional_1/src/main.nr index 176106ba890..5064c82bce9 100644 --- a/tooling/nargo_cli/tests/execution_success/conditional_1/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/conditional_1/src/main.nr @@ -21,7 +21,7 @@ fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { //Test case for short-circuit let mut data = [0 as u32; 32]; let mut ba = a; - for i in 0..32 { + for i in 0..32 { let i_u32 = i as u32; if i_u32 == a { for j in 0..4 { @@ -37,10 +37,8 @@ fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { } assert(data[31] == 0); assert(ba != 13); - - //Test case for conditional with arrays from function parameters - let b = sort([1,2,3,4]); + let b = sort([1, 2, 3, 4]); assert(b[0] == 1); if a == 0 { @@ -51,7 +49,7 @@ fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { c[0] = 1; c[1] = c[2] / a + 11 % a; let f1 = a as Field; - assert(10/f1 != 0); + assert(10 / f1 != 0); } assert(c[0] == 3); @@ -65,7 +63,6 @@ fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { assert(y == result[0]); c = sort(c); assert(c[0] == 0); - //test 1 let mut x: u32 = 0; if a == 0 { @@ -84,7 +81,6 @@ fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { x = 3; } assert(x == 2); - //test2: loops let mut x: u32 = 0; x = a - a; diff --git a/tooling/nargo_cli/tests/execution_success/conditional_2/Nargo.toml b/tooling/nargo_cli/tests/execution_success/conditional_2/Nargo.toml index 1401a715eef..153c5d38b99 100644 --- a/tooling/nargo_cli/tests/execution_success/conditional_2/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/conditional_2/Nargo.toml @@ -2,6 +2,5 @@ name = "conditional_2" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/conditional_2/src/main.nr b/tooling/nargo_cli/tests/execution_success/conditional_2/src/main.nr index 70237d4b638..5b3f64f6be5 100644 --- a/tooling/nargo_cli/tests/execution_success/conditional_2/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/conditional_2/src/main.nr @@ -4,14 +4,14 @@ fn must_be_zero(x: u8) { assert(x == 0); } -fn test3 (x: u8) { +fn test3(x: u8) { if x == 0 { must_be_zero(x); } } fn test4() -> [u32; 4] { - let b: [u32; 4] = [1,2,3,4]; + let b: [u32; 4] = [1, 2, 3, 4]; b } @@ -29,7 +29,6 @@ fn main(a: u32, mut c: [u32; 4]) { assert(c[1] == 2); test5(4); - // Test case for function synchronisation let mut c_sync = 0; if a == 42 { @@ -40,7 +39,7 @@ fn main(a: u32, mut c: [u32; 4]) { assert(c_sync == 6); } -fn test5(a : u32) { +fn test5(a: u32) { if a > 1 { let q = a / 2; assert(q == 2); diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_421/Nargo.toml b/tooling/nargo_cli/tests/execution_success/conditional_regression_421/Nargo.toml index 9fddef0e86f..987b51ae126 100644 --- a/tooling/nargo_cli/tests/execution_success/conditional_regression_421/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/conditional_regression_421/Nargo.toml @@ -2,6 +2,5 @@ name = "conditional_regression_421" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_421/src/main.nr b/tooling/nargo_cli/tests/execution_success/conditional_regression_421/src/main.nr index 60052c20610..5789afb76db 100644 --- a/tooling/nargo_cli/tests/execution_success/conditional_regression_421/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/conditional_regression_421/src/main.nr @@ -2,13 +2,9 @@ fn main(a: u32, mut c: [u32; 4]) { //Issue reported in #421 if a == c[0] { assert(c[0] == 0); - } else { - if a == c[1] { - assert(c[1] == 0); - } else { - if a == c[2] { - assert(c[2] == 0); - } - } + } else if a == c[1] { + assert(c[1] == 0); + } else if a == c[2] { + assert(c[2] == 0); } } diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_661/Nargo.toml b/tooling/nargo_cli/tests/execution_success/conditional_regression_661/Nargo.toml index 902408f5d56..ed11341c5b0 100644 --- a/tooling/nargo_cli/tests/execution_success/conditional_regression_661/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/conditional_regression_661/Nargo.toml @@ -2,6 +2,5 @@ name = "conditional_regression_661" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_661/src/main.nr b/tooling/nargo_cli/tests/execution_success/conditional_regression_661/src/main.nr index efdc1ddbce4..03102eb775e 100644 --- a/tooling/nargo_cli/tests/execution_success/conditional_regression_661/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/conditional_regression_661/src/main.nr @@ -9,19 +9,19 @@ fn main(a: u32, mut c: [u32; 4]) { assert(c_661[0] < 20000); } -fn test5(a : u32) { +fn test5(a: u32) { if a > 1 { let q = a / 2; assert(q == 2); } } -fn issue_661_foo(array: [u32;4], b:u32) ->[u32;1] { +fn issue_661_foo(array: [u32;4], b: u32) -> [u32;1] { [array[0] + b] } -fn issue_661_bar(a : [u32;4]) ->[u32;4] { - let mut b: [u32; 4] = [0;4]; +fn issue_661_bar(a: [u32;4]) -> [u32;4] { + let mut b: [u32; 4] = [0; 4]; b[0]=a[0]+1; b } diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/Nargo.toml b/tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/Nargo.toml index 24c16982cc4..92f5a869bc4 100644 --- a/tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/Nargo.toml @@ -2,6 +2,5 @@ name = "conditional_regression_short_circuit" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/src/main.nr b/tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/src/main.nr index 57387ed5052..d260fa49dc3 100644 --- a/tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/conditional_regression_short_circuit/src/main.nr @@ -8,7 +8,7 @@ fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { bar(a as Field); if a == 3 { - c = test4(); + c = test4(); } assert(c[1] != 2); call_intrinsic(x, result); @@ -19,7 +19,7 @@ fn foo() { x /= 0; } -fn bar(x:Field) { +fn bar(x: Field) { if x == 15 { foo(); } @@ -33,6 +33,6 @@ fn call_intrinsic(x: [u8; 5], result: [u8; 32]) { } fn test4() -> [u32; 4] { - let b: [u32; 4] = [1,2,3,4]; + let b: [u32; 4] = [1, 2, 3, 4]; b } diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/Nargo.toml b/tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/Nargo.toml new file mode 100644 index 00000000000..75c4fb43b2f --- /dev/null +++ b/tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "conditional_regression_underflow" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/Prover.toml b/tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/Prover.toml new file mode 100644 index 00000000000..ca65e8b9428 --- /dev/null +++ b/tooling/nargo_cli/tests/execution_success/conditional_regression_underflow/Prover.toml @@ -0,0 +1 @@ +x = "4" \ No newline at end of file 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 new file mode 100644 index 00000000000..be70b67be5e --- /dev/null +++ b/tooling/nargo_cli/tests/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; + } +} \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/custom_entry/Nargo.toml b/tooling/nargo_cli/tests/execution_success/custom_entry/Nargo.toml index a8cc75072b1..35cf2e080c1 100644 --- a/tooling/nargo_cli/tests/execution_success/custom_entry/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/custom_entry/Nargo.toml @@ -3,6 +3,5 @@ name = "custom_entry" type = "bin" entry = "src/foobarbaz.nr" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/debug_logs/Nargo.toml b/tooling/nargo_cli/tests/execution_success/debug_logs/Nargo.toml index edc03c152cf..9550d50cf15 100644 --- a/tooling/nargo_cli/tests/execution_success/debug_logs/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/debug_logs/Nargo.toml @@ -2,6 +2,4 @@ name = "debug_logs" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/debug_logs/src/main.nr b/tooling/nargo_cli/tests/execution_success/debug_logs/src/main.nr index 23c6b8a76d4..6accdf725d9 100644 --- a/tooling/nargo_cli/tests/execution_success/debug_logs/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/debug_logs/src/main.nr @@ -1,9 +1,8 @@ use dep::std; -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { let string = "i: {i}, j: {j}"; std::println(string); - // A `fmtstr` lets you easily perform string interpolation. let fmt_str: fmtstr<14, (Field, Field)> = f"i: {x}, j: {y}"; let fmt_str = string_identity(fmt_str); diff --git a/tooling/nargo_cli/tests/execution_success/diamond_deps_0/Nargo.toml b/tooling/nargo_cli/tests/execution_success/diamond_deps_0/Nargo.toml index 6b1dd65ba32..8b75d71ae12 100644 --- a/tooling/nargo_cli/tests/execution_success/diamond_deps_0/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/diamond_deps_0/Nargo.toml @@ -2,7 +2,6 @@ name = "diamond_deps_0" type = "bin" authors = [""] -compiler_version = "0.7.1" [dependencies] dep1 = { path = "../../test_libraries/diamond_deps_1" } diff --git a/tooling/nargo_cli/tests/execution_success/diamond_deps_0/src/main.nr b/tooling/nargo_cli/tests/execution_success/diamond_deps_0/src/main.nr index 1c4dba1c791..ca95c6e0aa8 100644 --- a/tooling/nargo_cli/tests/execution_success/diamond_deps_0/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/diamond_deps_0/src/main.nr @@ -2,6 +2,6 @@ use dep::dep1::call_dep1_then_dep2; use dep::dep2::call_dep2; use dep::dep2::RESOLVE_THIS; -fn main(x : Field, y : pub Field) -> pub Field { +fn main(x: Field, y: pub Field) -> pub Field { call_dep1_then_dep2(x, y) + call_dep2(x, y) + RESOLVE_THIS } diff --git a/tooling/nargo_cli/tests/execution_success/distinct_keyword/Nargo.toml b/tooling/nargo_cli/tests/execution_success/distinct_keyword/Nargo.toml index b7de54ea5cc..3f1b1386ba7 100644 --- a/tooling/nargo_cli/tests/execution_success/distinct_keyword/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/distinct_keyword/Nargo.toml @@ -2,6 +2,5 @@ name = "distinct_keyword" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/double_verify_proof/Nargo.toml b/tooling/nargo_cli/tests/execution_success/double_verify_proof/Nargo.toml index 61aaabfcf5b..a4edd2e4288 100644 --- a/tooling/nargo_cli/tests/execution_success/double_verify_proof/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/double_verify_proof/Nargo.toml @@ -2,6 +2,4 @@ name = "double_verify_proof" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] 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 index c679730e3c0..ecc00bbd560 100644 --- 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 @@ -1,28 +1,24 @@ 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], + 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_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(), + 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 - ); + output_aggregation_object_a); let mut output = [0; 16]; for i in 0..16 { diff --git a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/Nargo.toml b/tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/Nargo.toml index 0f8111dc9f6..58fdf96f0e3 100644 --- a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/Nargo.toml @@ -3,6 +3,5 @@ name = "ecdsa_secp256k1" description = "ECDSA secp256k1 verification" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] 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 index 5af8008f291..552fcea9af7 100644 --- a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/ecdsa_secp256k1/src/main.nr @@ -1,10 +1,10 @@ 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 +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); + assert(hashed_message == expected); let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); - assert(valid_signature); + assert(valid_signature); } diff --git a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/Nargo.toml b/tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/Nargo.toml index 738b049060a..87e8d529566 100644 --- a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/Nargo.toml @@ -3,6 +3,5 @@ name = "ecdsa_secp256r1" description = "ECDSA secp256r1 verification" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/src/main.nr b/tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/src/main.nr index eda78cd81a6..d23573d13a6 100644 --- a/tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/ecdsa_secp256r1/src/main.nr @@ -1,6 +1,6 @@ use dep::std; -fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { +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); + assert(valid_signature); } diff --git a/tooling/nargo_cli/tests/execution_success/eddsa/Nargo.toml b/tooling/nargo_cli/tests/execution_success/eddsa/Nargo.toml index 039da3a7074..0f545c2febc 100644 --- a/tooling/nargo_cli/tests/execution_success/eddsa/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/eddsa/Nargo.toml @@ -3,6 +3,5 @@ name = "eddsa" description = "Eddsa verification" type = "bin" authors = [""] -compiler_version = "0.3.2" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/eddsa/src/main.nr b/tooling/nargo_cli/tests/execution_success/eddsa/src/main.nr index 870a20fe01a..12e8ea92785 100644 --- a/tooling/nargo_cli/tests/execution_success/eddsa/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/eddsa/src/main.nr @@ -9,17 +9,15 @@ fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) { let pub_key_a = bjj.curve.mul(_priv_key_a, bjj.curve.gen); // let pub_key_b = bjj.curve.mul(_priv_key_b, bjj.curve.gen); - // Manually computed as fields can't use modulo. Importantantly the commitment is within // the subgroup order. Note that choice of hash is flexible for this step. - // let r_a = hash::pedersen([_priv_key_a, msg])[0] % bjj.suborder; // modulus computed manually + // let r_a = hash::pedersen_commitment([_priv_key_a, msg])[0] % bjj.suborder; // modulus computed manually let r_a = 1414770703199880747815475415092878800081323795074043628810774576767372531818; - // let r_b = hash::pedersen([_priv_key_b, msg])[0] % bjj.suborder; // modulus computed manually + // let r_b = hash::pedersen_commitment([_priv_key_b, msg])[0] % bjj.suborder; // modulus computed manually let r_b = 571799555715456644614141527517766533395606396271089506978608487688924659618; let r8_a = bjj.curve.mul(r_a, bjj.base8); let r8_b = bjj.curve.mul(r_b, bjj.base8); - // let h_a: [Field; 6] = hash::poseidon::bn254::hash_5([ // r8_a.x, // r8_a.y, @@ -27,7 +25,6 @@ fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) { // pub_key_a.y, // msg, // ]); - // let h_b: [Field; 6] = hash::poseidon::bn254::hash_5([ // r8_b.x, // r8_b.y, @@ -35,18 +32,14 @@ fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) { // pub_key_b.y, // msg, // ]); - // let s_a = (r_a + _priv_key_a * h_a) % bjj.suborder; // modulus computed manually - let s_a = 30333430637424319196043722294837632681219980330991241982145549329256671548; + let s_a = 30333430637424319196043722294837632681219980330991241982145549329256671548; // let s_b = (r_b + _priv_key_b * h_b) % bjj.suborder; // modulus computed manually let s_b = 1646085314320208098241070054368798527940102577261034947654839408482102287019; - // User A verifies their signature over the message assert(eddsa_poseidon_verify(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg)); - // User B's signature over the message can't be used with user A's pub key assert(!eddsa_poseidon_verify(pub_key_a.x, pub_key_a.y, s_b, r8_b.x, r8_b.y, msg)); - // User A's signature over the message can't be used with another message assert(!eddsa_poseidon_verify(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg + 1)); } diff --git a/tooling/nargo_cli/tests/execution_success/field_attribute/Nargo.toml b/tooling/nargo_cli/tests/execution_success/field_attribute/Nargo.toml index f625d7e41f2..37487d0043c 100644 --- a/tooling/nargo_cli/tests/execution_success/field_attribute/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/field_attribute/Nargo.toml @@ -2,6 +2,5 @@ name = "field_attribute" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/field_attribute/src/main.nr b/tooling/nargo_cli/tests/execution_success/field_attribute/src/main.nr index d6d71781899..dda83db40de 100644 --- a/tooling/nargo_cli/tests/execution_success/field_attribute/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/field_attribute/src/main.nr @@ -16,4 +16,4 @@ fn foo() -> u32 { #[field(bls12_381)] fn foo() -> u32 { 3 -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/execution_success/generics/Nargo.toml b/tooling/nargo_cli/tests/execution_success/generics/Nargo.toml index 18bdae1ab08..19c8ff28ec7 100644 --- a/tooling/nargo_cli/tests/execution_success/generics/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/generics/Nargo.toml @@ -2,6 +2,5 @@ name = "generics" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/generics/src/main.nr b/tooling/nargo_cli/tests/execution_success/generics/src/main.nr index 9a1effcd318..3edce1ed8e7 100644 --- a/tooling/nargo_cli/tests/execution_success/generics/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/generics/src/main.nr @@ -37,16 +37,13 @@ fn main(x: Field, y: Field) { foo(bar1); foo(bar2); - // Test generic impls let int1 = BigInt { limbs: [1] }; let int2 = BigInt { limbs: [2] }; let BigInt { limbs } = int1.second(int2).first(int1); assert(limbs == int2.limbs); - // Test impl exclusively for Bar assert(bar1.get_other() == bar1.other); - // Expected type error // assert(bar2.get_other() == bar2.other); let one = x; diff --git a/tooling/nargo_cli/tests/execution_success/global_consts/Nargo.toml b/tooling/nargo_cli/tests/execution_success/global_consts/Nargo.toml index 2452ad8edb3..3b4d6be2353 100644 --- a/tooling/nargo_cli/tests/execution_success/global_consts/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/global_consts/Nargo.toml @@ -2,6 +2,5 @@ name = "global_consts" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/global_consts/src/baz.nr b/tooling/nargo_cli/tests/execution_success/global_consts/src/baz.nr index d5b13407574..4271de81118 100644 --- a/tooling/nargo_cli/tests/execution_success/global_consts/src/baz.nr +++ b/tooling/nargo_cli/tests/execution_success/global_consts/src/baz.nr @@ -1,5 +1,5 @@ -pub fn from_baz(x : [Field; crate::foo::MAGIC_NUMBER]) { - for i in 0..crate::foo::MAGIC_NUMBER { - assert(x[i] == crate::foo::MAGIC_NUMBER); - }; +pub fn from_baz(x: [Field; crate::foo::MAGIC_NUMBER]) { + for i in 0..crate::foo::MAGIC_NUMBER { + assert(x[i] == crate::foo::MAGIC_NUMBER); + } } diff --git a/tooling/nargo_cli/tests/execution_success/global_consts/src/foo.nr b/tooling/nargo_cli/tests/execution_success/global_consts/src/foo.nr index 2d28111728b..7b0ae75b74b 100644 --- a/tooling/nargo_cli/tests/execution_success/global_consts/src/foo.nr +++ b/tooling/nargo_cli/tests/execution_success/global_consts/src/foo.nr @@ -4,8 +4,8 @@ global N: Field = 5; global MAGIC_NUMBER: Field = 3; global TYPE_INFERRED = 42; -pub fn from_foo(x : [Field; bar::N]) { - for i in 0..bar::N { - assert(x[i] == bar::N); - }; +pub fn from_foo(x: [Field; bar::N]) { + for i in 0..bar::N { + assert(x[i] == bar::N); + } } diff --git a/tooling/nargo_cli/tests/execution_success/global_consts/src/foo/bar.nr b/tooling/nargo_cli/tests/execution_success/global_consts/src/foo/bar.nr index b4b43442cc8..b8d0b85b0f3 100644 --- a/tooling/nargo_cli/tests/execution_success/global_consts/src/foo/bar.nr +++ b/tooling/nargo_cli/tests/execution_success/global_consts/src/foo/bar.nr @@ -1,5 +1,5 @@ global N: Field = 5; -pub fn from_bar(x : Field) -> Field { +pub fn from_bar(x: Field) -> Field { x * N } diff --git a/tooling/nargo_cli/tests/execution_success/global_consts/src/main.nr b/tooling/nargo_cli/tests/execution_success/global_consts/src/main.nr index 0c3a4fcd771..a749ec77da6 100644 --- a/tooling/nargo_cli/tests/execution_success/global_consts/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/global_consts/src/main.nr @@ -6,7 +6,6 @@ global L: Field = 10; // Unused globals currently allowed global N: Field = 5; global T_LEN = 2; // Type inference is allowed on globals //global N: Field = 5; // Uncomment to see duplicate globals error - struct Dummy { x: [Field; N], y: [Field; foo::MAGIC_NUMBER] @@ -18,52 +17,56 @@ struct Test { global VALS: [Test; 1] = [Test { v: 100 }]; global NESTED = [VALS, VALS]; -fn main(a: [Field; M + N - N], b: [Field; 30 + N / 2], c : pub [Field; foo::MAGIC_NUMBER], d: [Field; foo::bar::N]) { +fn main( + a: [Field; M + N - N], + b: [Field; 30 + N / 2], + c: pub [Field; foo::MAGIC_NUMBER], + d: [Field; foo::bar::N] +) { let test_struct = Dummy { x: d, y: c }; - for i in 0..foo::MAGIC_NUMBER { - assert(c[i] == foo::MAGIC_NUMBER); - assert(test_struct.y[i] == foo::MAGIC_NUMBER); - assert(test_struct.y[i] != NESTED[1][0].v); - } + for i in 0..foo::MAGIC_NUMBER { + assert(c[i] == foo::MAGIC_NUMBER); + assert(test_struct.y[i] == foo::MAGIC_NUMBER); + assert(test_struct.y[i] != NESTED[1][0].v); + } - assert(N != M); + assert(N != M); let expected: u32 = 42; - assert(foo::TYPE_INFERRED == expected); + assert(foo::TYPE_INFERRED == expected); let mut y = 5; let mut x = M; - for i in 0..N*N { - let M: Field = 10; - x = M; - - y = i; - } - assert(y == 24); - assert(x == 10); + for i in 0..N * N { + let M: Field = 10; + x = M; + + y = i; + } + assert(y == 24); + assert(x == 10); let q = multiplyByM(3); - assert(q == 96); + assert(q == 96); arrays_neq(a, b); let t: [Field; T_LEN] = [N, M]; - assert(t[1] == 32); + assert(t[1] == 32); - assert(15 == mysubmodule::my_helper()); + assert(15 == mysubmodule::my_helper()); let add_submodules_N = mysubmodule::N + foo::bar::N; - assert(15 == add_submodules_N); + assert(15 == add_submodules_N); let add_from_bar_N = mysubmodule::N + foo::bar::from_bar(1); - assert(15 == add_from_bar_N); - - // Example showing an array filled with (mysubmodule::N + 2) 0's + assert(15 == add_from_bar_N); + // Example showing an array filled with (mysubmodule::N + 2) 0's let sugared = [0; mysubmodule::N + 2]; - assert(sugared[mysubmodule::N + 1] == 0); + assert(sugared[mysubmodule::N + 1] == 0); let arr: [Field; mysubmodule::N] = [N; 10]; - assert((arr[0] == 5) & (arr[9] == 5)); + assert((arr[0] == 5) & (arr[9] == 5)); foo::from_foo(d); baz::from_baz(c); @@ -74,20 +77,20 @@ fn multiplyByM(x: Field) -> Field { } fn arrays_neq(a: [Field; M], b: [Field; M]) { - assert(a != b); + assert(a != b); } mod mysubmodule { - global N: Field = 10; - global L: Field = 50; - - fn my_bool_or(x: u1, y: u1) { - assert(x | y == 1); - } - - pub fn my_helper() -> Field { - let N: Field = 15; // Like in Rust, local variables override globals - let x = N; - x - } + global N: Field = 10; + global L: Field = 50; + + fn my_bool_or(x: u1, y: u1) { + assert(x | y == 1); + } + + pub fn my_helper() -> Field { + let N: Field = 15; // Like in Rust, local variables override globals + let x = N; + x + } } diff --git a/tooling/nargo_cli/tests/execution_success/hash_to_field/Nargo.toml b/tooling/nargo_cli/tests/execution_success/hash_to_field/Nargo.toml index d78b59118f9..a00a7bdc050 100644 --- a/tooling/nargo_cli/tests/execution_success/hash_to_field/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/hash_to_field/Nargo.toml @@ -2,6 +2,5 @@ name = "hash_to_field" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/hash_to_field/src/main.nr b/tooling/nargo_cli/tests/execution_success/hash_to_field/src/main.nr index ffc334179ee..5af1c5af55e 100644 --- a/tooling/nargo_cli/tests/execution_success/hash_to_field/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/hash_to_field/src/main.nr @@ -1,5 +1,5 @@ use dep::std; -fn main(input : Field) -> pub Field { +fn main(input: Field) -> pub Field { std::hash::hash_to_field([input]) } diff --git a/tooling/nargo_cli/tests/execution_success/higher_order_functions/Nargo.toml b/tooling/nargo_cli/tests/execution_success/higher_order_functions/Nargo.toml index 9dc419d1678..8f8a79e7e83 100644 --- a/tooling/nargo_cli/tests/execution_success/higher_order_functions/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/higher_order_functions/Nargo.toml @@ -2,6 +2,5 @@ name = "higher_order_functions" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] 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 index 71eacfe4da5..479cdbbe7bf 100644 --- 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 @@ -4,29 +4,24 @@ fn main(w: Field) -> pub Field { // 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); - - + })(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); @@ -41,17 +36,14 @@ fn main(w: Field) -> pub Field { 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)); @@ -59,7 +51,6 @@ fn test_array_functions() { 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? // @@ -70,10 +61,8 @@ fn test_array_functions() { // // 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); } @@ -93,7 +82,6 @@ fn add1(x: Field) -> Field { 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 @@ -103,11 +91,7 @@ fn twice(f: fn(Field) -> Field, x: Field) -> Field { fn regression_2154() { let x: u32 = 32; - let closure_if_else = if x > 2 { - || x - } else { - || x + 2342 - }; + 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/tooling/nargo_cli/tests/execution_success/if_else_chain/Nargo.toml index fc5fffa2185..2f0dc93d120 100644 --- a/tooling/nargo_cli/tests/execution_success/if_else_chain/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/if_else_chain/Nargo.toml @@ -2,6 +2,5 @@ name = "if_else_chain" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/if_else_chain/src/main.nr b/tooling/nargo_cli/tests/execution_success/if_else_chain/src/main.nr index 9fd5fbfd3d3..2705d5b3111 100644 --- a/tooling/nargo_cli/tests/execution_success/if_else_chain/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/if_else_chain/src/main.nr @@ -9,7 +9,7 @@ fn main(a: u32, mut c: [u32; 4]) { // expect to match this case assert(c[3] == 0); } else { - assert(c[0] == 10); + assert(c[0] == 10); } } diff --git a/tooling/nargo_cli/tests/execution_success/import/Nargo.toml b/tooling/nargo_cli/tests/execution_success/import/Nargo.toml index 858c2a29840..c92328f106c 100644 --- a/tooling/nargo_cli/tests/execution_success/import/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/import/Nargo.toml @@ -2,6 +2,5 @@ name = "import" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/import/src/import.nr b/tooling/nargo_cli/tests/execution_success/import/src/import.nr index 4df05bbc288..ef3f0d94c28 100644 --- a/tooling/nargo_cli/tests/execution_success/import/src/import.nr +++ b/tooling/nargo_cli/tests/execution_success/import/src/import.nr @@ -1,3 +1,3 @@ -pub fn hello(x : Field) -> Field { +pub fn hello(x: Field) -> Field { x } diff --git a/tooling/nargo_cli/tests/execution_success/import/src/main.nr b/tooling/nargo_cli/tests/execution_success/import/src/main.nr index cb6476480d8..7dcc16fed16 100644 --- a/tooling/nargo_cli/tests/execution_success/import/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/import/src/main.nr @@ -1,8 +1,8 @@ mod import; use crate::import::hello; -fn main(x : Field, y : Field) { - let _k = dep::std::hash::pedersen([x]); +fn main(x: Field, y: Field) { + let _k = dep::std::hash::pedersen_commitment([x]); let _l = hello(x); assert(x != import::hello(y)); diff --git a/tooling/nargo_cli/tests/execution_success/integer_array_indexing/Nargo.toml b/tooling/nargo_cli/tests/execution_success/integer_array_indexing/Nargo.toml index 3cec63d465b..6e639b64f58 100644 --- a/tooling/nargo_cli/tests/execution_success/integer_array_indexing/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/integer_array_indexing/Nargo.toml @@ -2,6 +2,5 @@ name = "integer_array_indexing" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/keccak256/Nargo.toml b/tooling/nargo_cli/tests/execution_success/keccak256/Nargo.toml index ab1a04b7c07..7e48c3b342c 100644 --- a/tooling/nargo_cli/tests/execution_success/keccak256/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/keccak256/Nargo.toml @@ -2,6 +2,5 @@ name = "keccak256" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/keccak256/src/main.nr b/tooling/nargo_cli/tests/execution_success/keccak256/src/main.nr index 9bca6a7c1bf..ff2167694d6 100644 --- a/tooling/nargo_cli/tests/execution_success/keccak256/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/keccak256/src/main.nr @@ -7,16 +7,15 @@ fn main(x: Field, result: [u8; 32]) { // The padding is taken care of by the program let digest = std::hash::keccak256([x as u8], 1); assert(digest == result); - //#1399: variable meesage size let message_size = 4; - let hash_a = std::hash::keccak256([1,2,3,4], message_size); - let hash_b = std::hash::keccak256([1,2,3,4,0,0,0,0], message_size); + let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); + let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); assert(hash_a == hash_b); let message_size_big = 8; - let hash_c = std::hash::keccak256([1,2,3,4,0,0,0,0], message_size_big); + let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); assert(hash_a != hash_c); } diff --git a/tooling/nargo_cli/tests/execution_success/main_bool_arg/Nargo.toml b/tooling/nargo_cli/tests/execution_success/main_bool_arg/Nargo.toml index 1a4e3657464..c1cedb6c657 100644 --- a/tooling/nargo_cli/tests/execution_success/main_bool_arg/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/main_bool_arg/Nargo.toml @@ -2,6 +2,5 @@ name = "main_bool_arg" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/main_bool_arg/src/main.nr b/tooling/nargo_cli/tests/execution_success/main_bool_arg/src/main.nr index 0615a7dbca4..111a23ec0c2 100644 --- a/tooling/nargo_cli/tests/execution_success/main_bool_arg/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/main_bool_arg/src/main.nr @@ -1,4 +1,4 @@ -fn main(x : bool, y: [bool;2]) { +fn main(x: bool, y: [bool;2]) { if x { assert(1 != 2); } diff --git a/tooling/nargo_cli/tests/execution_success/merkle_insert/Nargo.toml b/tooling/nargo_cli/tests/execution_success/merkle_insert/Nargo.toml index 3eb97c30cac..f09458411d8 100644 --- a/tooling/nargo_cli/tests/execution_success/merkle_insert/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/merkle_insert/Nargo.toml @@ -2,6 +2,5 @@ name = "merkle_insert" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/merkle_insert/Prover.toml b/tooling/nargo_cli/tests/execution_success/merkle_insert/Prover.toml index 3f69ad1cffb..0656908c063 100644 --- a/tooling/nargo_cli/tests/execution_success/merkle_insert/Prover.toml +++ b/tooling/nargo_cli/tests/execution_success/merkle_insert/Prover.toml @@ -1,11 +1,11 @@ -old_root = "0x200fbe381993186866de8eb5a9cc33845de6b084be3ff67f6e34d35b8a786157" -old_leaf = "0x1cdcf02431ba623767fe389337d011df1048dcc24b98ed81cec97627bab454a0" +old_root = "0x2131c74af6250d1246797588ff075b672e3d2e6805f9c6b313ade8f6b9e12802" +old_leaf = "0x2df8b940e5890e4e1377e05373fae69a1d754f6935e6a780b666947431f2cdcd" old_hash_path = [ - "0x1cdcf02431ba623767fe389337d011df1048dcc24b98ed81cec97627bab454a0", - "0x0b5e9666e7323ce925c28201a97ddf4144ac9d148448ed6f49f9008719c1b85b", - "0x22ec636f8ad30ef78c42b7fe2be4a4cacf5a445cfb5948224539f59a11d70775", + "0x03542cb720369f19a74fd05b4edfbedb27a78514ad3283f1b3270a1656cced8e", + "0x1278272f6e617666b18c52349c4bbe94249a8ab59add2ee0a142168a92b7ffc2", + "0x2547cfd7699ad1f331fb77b30a3445c6043a4c62b5b1215356b2924607bf937b", ] -new_root = "0x029ead881a6684995190589a67874f188f33a433211df82f56c1351c96530387" -leaf = "0x085ca53be9c9d95b57e6e5fc91c5d531ad9e63e85dd71af7e35562991774b435" +new_root = "0x25e2a8ee5b85e5b546ae27832b9b53f5fae5b371e3e7f8cddda839f41669fc68" +leaf = "0x23fe6c8f2426b793f0f156f57efbecbea52e951af761634a85e80cc1a9fb5003" index = "0" mimc_input = [12, 45, 78, 41] diff --git a/tooling/nargo_cli/tests/execution_success/merkle_insert/src/main.nr b/tooling/nargo_cli/tests/execution_success/merkle_insert/src/main.nr index 3de10520037..ac9a7b34ea3 100644 --- a/tooling/nargo_cli/tests/execution_success/merkle_insert/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/merkle_insert/src/main.nr @@ -1,4 +1,5 @@ use dep::std; +use dep::std::hash::mimc; fn main( old_root: Field, @@ -7,14 +8,14 @@ fn main( new_root: pub Field, leaf: Field, index: Field, - mimc_input: [Field; 4], + mimc_input: [Field; 4] ) { assert(old_root == std::merkle::compute_merkle_root(old_leaf, index, old_hash_path)); let calculated_root = std::merkle::compute_merkle_root(leaf, index, old_hash_path); assert(new_root == calculated_root); - let h = std::hash::mimc_bn254(mimc_input); + let h = mimc::mimc_bn254(mimc_input); // Regression test for PR #891 std::println(h); assert(h == 18226366069841799622585958305961373004333097209608110160936134895615261821931); diff --git a/tooling/nargo_cli/tests/execution_success/mock_oracle/Nargo.toml b/tooling/nargo_cli/tests/execution_success/mock_oracle/Nargo.toml index f626c2967cc..b2916487e8c 100644 --- a/tooling/nargo_cli/tests/execution_success/mock_oracle/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/mock_oracle/Nargo.toml @@ -2,6 +2,5 @@ name = "mock_oracle" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/mock_oracle/src/main.nr b/tooling/nargo_cli/tests/execution_success/mock_oracle/src/main.nr index 07553f05d6c..90fca7993cc 100644 --- a/tooling/nargo_cli/tests/execution_success/mock_oracle/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/mock_oracle/src/main.nr @@ -9,12 +9,9 @@ struct Point { unconstrained fn foo_oracle(_point: Point, _array: [Field; 4]) -> Field {} unconstrained fn main() { - let array = [1,2,3,4]; - let another_array = [4,3,2,1]; - let point = Point { - x: 14, - y: 27, - }; + let array = [1, 2, 3, 4]; + let another_array = [4, 3, 2, 1]; + let point = Point { x: 14, y: 27 }; OracleMock::mock("foo").returns(42).times(1); let mock = OracleMock::mock("foo").returns(0); diff --git a/tooling/nargo_cli/tests/execution_success/modules/Nargo.toml b/tooling/nargo_cli/tests/execution_success/modules/Nargo.toml index b4f9b469ea8..ab1d6e962d7 100644 --- a/tooling/nargo_cli/tests/execution_success/modules/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/modules/Nargo.toml @@ -2,6 +2,5 @@ name = "modules" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/modules/src/foo.nr b/tooling/nargo_cli/tests/execution_success/modules/src/foo.nr index 4df05bbc288..ef3f0d94c28 100644 --- a/tooling/nargo_cli/tests/execution_success/modules/src/foo.nr +++ b/tooling/nargo_cli/tests/execution_success/modules/src/foo.nr @@ -1,3 +1,3 @@ -pub fn hello(x : Field) -> Field { +pub fn hello(x: Field) -> Field { x } diff --git a/tooling/nargo_cli/tests/execution_success/modules_more/Nargo.toml b/tooling/nargo_cli/tests/execution_success/modules_more/Nargo.toml index 5acf61a71a7..bfcfe08fa79 100644 --- a/tooling/nargo_cli/tests/execution_success/modules_more/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/modules_more/Nargo.toml @@ -2,6 +2,5 @@ name = "modules_more" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/modules_more/src/foo.nr b/tooling/nargo_cli/tests/execution_success/modules_more/src/foo.nr index ee0d20082f5..fa531a1a2f0 100644 --- a/tooling/nargo_cli/tests/execution_success/modules_more/src/foo.nr +++ b/tooling/nargo_cli/tests/execution_success/modules_more/src/foo.nr @@ -1,5 +1,5 @@ mod bar; -fn hello(x : Field) -> Field { +fn hello(x: Field) -> Field { x } diff --git a/tooling/nargo_cli/tests/execution_success/modules_more/src/foo/bar.nr b/tooling/nargo_cli/tests/execution_success/modules_more/src/foo/bar.nr index 3d07fd9b72f..1665f720be6 100644 --- a/tooling/nargo_cli/tests/execution_success/modules_more/src/foo/bar.nr +++ b/tooling/nargo_cli/tests/execution_success/modules_more/src/foo/bar.nr @@ -1,3 +1,3 @@ -pub fn from_bar(x : Field) -> Field { +pub fn from_bar(x: Field) -> Field { x } diff --git a/tooling/nargo_cli/tests/execution_success/modules_more/src/main.nr b/tooling/nargo_cli/tests/execution_success/modules_more/src/main.nr index 8862e5a8650..93b76d62845 100644 --- a/tooling/nargo_cli/tests/execution_success/modules_more/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/modules_more/src/main.nr @@ -1,5 +1,4 @@ mod foo; - // An example of the module system fn main(x: Field, y: Field) { assert(x != foo::bar::from_bar(y)); diff --git a/tooling/nargo_cli/tests/execution_success/modulus/Nargo.toml b/tooling/nargo_cli/tests/execution_success/modulus/Nargo.toml index 5a1309a2a9d..256eeef058f 100644 --- a/tooling/nargo_cli/tests/execution_success/modulus/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/modulus/Nargo.toml @@ -2,6 +2,5 @@ name = "modulus" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/modulus/src/main.nr b/tooling/nargo_cli/tests/execution_success/modulus/src/main.nr index e8d0cc0541a..35f63fdc8c5 100644 --- a/tooling/nargo_cli/tests/execution_success/modulus/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/modulus/src/main.nr @@ -1,6 +1,6 @@ use dep::std; -fn main(bn254_modulus_be_bytes : [u8; 32], bn254_modulus_be_bits : [u1; 254]) { +fn main(bn254_modulus_be_bytes: [u8; 32], bn254_modulus_be_bits: [u1; 254]) { let modulus_size = std::field::modulus_num_bits(); // NOTE: The constraints used in this circuit will only work when testing nargo with the plonk bn254 backend assert(modulus_size == 254); @@ -11,7 +11,7 @@ fn main(bn254_modulus_be_bytes : [u8; 32], bn254_modulus_be_bits : [u1; 254]) { } let modulus_le_byte_array = std::field::modulus_le_bytes(); for i in 0..32 { - assert(modulus_le_byte_array[i] == bn254_modulus_be_bytes[31-i]); + assert(modulus_le_byte_array[i] == bn254_modulus_be_bytes[31 - i]); } let modulus_be_bits = std::field::modulus_be_bits(); @@ -20,6 +20,6 @@ fn main(bn254_modulus_be_bytes : [u8; 32], bn254_modulus_be_bits : [u1; 254]) { } let modulus_le_bits = std::field::modulus_le_bits(); for i in 0..254 { - assert(modulus_le_bits[i] == bn254_modulus_be_bits[253-i]); + assert(modulus_le_bits[i] == bn254_modulus_be_bits[253 - i]); } } diff --git a/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/Nargo.toml b/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/Nargo.toml index 5be06d0f8af..72642bebc15 100644 --- a/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/Nargo.toml @@ -2,6 +2,5 @@ name = "nested_array_dynamic" type = "bin" authors = [""] -compiler_version = "0.11.1" [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/src/main.nr b/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/src/main.nr index 5538c08d778..2c53822d6b9 100644 --- a/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/nested_array_dynamic/src/main.nr @@ -13,7 +13,7 @@ struct FooParent { foos: [Foo; 4], } -fn main(mut x : [Foo; 4], y : pub Field) { +fn main(mut x: [Foo; 4], y: pub Field) { assert(x[y - 3].a == 1); assert(x[y - 3].b == [2, 3, 20]); assert(x[y - 2].a == 4); @@ -23,14 +23,13 @@ fn main(mut x : [Foo; 4], y : pub Field) { assert(x[y].a == 10); assert(x[y].b == [11, 12, 23]); assert(x[y].bar.inner == [109, 110, 111]); - // Check dynamic array set if y != 2 { x[y].a = 50; } else { x[y].a = 100; } - assert(x[y].a == 50); + assert(x[3].a == 50); if y == 2 { x[y - 1].b = [50, 51, 52]; @@ -38,7 +37,7 @@ fn main(mut x : [Foo; 4], y : pub Field) { x[y - 1].b = [100, 101, 102]; } assert(x[2].b == [100, 101, 102]); - + 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]); @@ -52,7 +51,7 @@ fn main(mut x : [Foo; 4], y : pub Field) { assert(foo_parents[y - 3].foos[y - 2].b == [5, 6, 21]); assert(foo_parents[y - 3].foos[y - 1].b == [100, 101, 102]); assert(foo_parents[y - 3].foos[y].b == [11, 12, 23]); - + assert(foo_parents[y - 3].foos[y].a == 50); assert(foo_parents[1].foos[1].b == [5, 6, 21]); @@ -70,10 +69,8 @@ fn main(mut x : [Foo; 4], y : pub Field) { foo_parents[y - 2].foos[y - 2].b[y - 1] = 1000; } assert(foo_parents[1].foos[1].b[2] == 5000); - // Set a dynamic array value foo_parents[y - 2].foos[y - 3].b = foo_parents[y - 2].foos[y - 2].b; assert(foo_parents[1].foos[0].b == [20, 19, 5000]); - } diff --git a/tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/Nargo.toml b/tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/Nargo.toml index bd5dfb8bef4..02d2e6e6a4e 100644 --- a/tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/Nargo.toml @@ -2,6 +2,4 @@ name = "nested_arrays_from_brillig" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/src/main.nr b/tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/src/main.nr index 46c4ebe938e..1bcbd7d5421 100644 --- a/tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/nested_arrays_from_brillig/src/main.nr @@ -13,9 +13,9 @@ fn access_nested(notes: [MyNote; 2]) -> Field { } unconstrained fn create_inside_brillig(values: [Field; 6]) -> [MyNote; 2] { - let header = Header { params: [values[0], values[1], values[2]]}; - let note0 = MyNote { array: [values[0], values[1]], plain : values[2], header }; - let note1 = MyNote { array: [values[3], values[4]], plain : values[5], header }; + let header = Header { params: [values[0], values[1], values[2]] }; + let note0 = MyNote { array: [values[0], values[1]], plain: values[2], header }; + let note1 = MyNote { array: [values[3], values[4]], plain: values[5], header }; [note0, note1] } diff --git a/tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/Nargo.toml b/tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/Nargo.toml index 00dfbffbe45..c8925ed97b4 100644 --- a/tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/Nargo.toml @@ -2,6 +2,4 @@ name = "nested_slice_dynamic" type = "bin" authors = [""] -compiler_version = "0.13.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/src/main.nr b/tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/src/main.nr index a2de5141786..a3007d5d0dc 100644 --- a/tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/nested_slice_dynamic/src/main.nr @@ -8,7 +8,7 @@ struct Foo { bar: Bar, } -fn main(y : Field) { +fn main(y: Field) { let foo_one = Foo { a: 1, b: [2, 3, 20], bar: Bar { inner: [100, 101, 102] } }; let foo_two = Foo { a: 4, b: [5, 6, 21], bar: Bar { inner: [103, 104, 105] } }; let foo_three = Foo { a: 7, b: [8, 9, 22], bar: Bar { inner: [106, 107, 108] } }; @@ -41,7 +41,7 @@ fn main(y : Field) { x[y - 1].b = [100, 101, 102]; } assert(x[2].b == [100, 101, 102]); - + 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]); diff --git a/tooling/nargo_cli/tests/execution_success/pedersen_check/Nargo.toml b/tooling/nargo_cli/tests/execution_success/pedersen_check/Nargo.toml index 3fc0bd9b79e..65fd3b5cf59 100644 --- a/tooling/nargo_cli/tests/execution_success/pedersen_check/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/pedersen_check/Nargo.toml @@ -2,6 +2,5 @@ name = "pedersen_check" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/pedersen_check/src/main.nr b/tooling/nargo_cli/tests/execution_success/pedersen_check/src/main.nr index 8d3460de98f..90ef218249b 100644 --- a/tooling/nargo_cli/tests/execution_success/pedersen_check/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/pedersen_check/src/main.nr @@ -1,21 +1,22 @@ use dep::std; fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: Field) { - let res = std::hash::pedersen([x, y]); - assert(res[0] == out_x); - assert(res[1] == out_y); + let res = std::hash::pedersen_commitment([x, y]); + assert(res.x == out_x); + assert(res.y == out_y); + let res_hash = std::hash::pedersen_hash_with_separator([x, y], 0); assert_eq(res_hash, out_hash); - assert(res_hash != res[0]); + assert(res_hash != res.x); - let raw_data = [x,y]; + let raw_data = [x, y]; let mut state = 0; for i in 0..2 { state = state * 8 + raw_data[i]; } state += salt; - let hash = std::hash::pedersen([state]); - assert(std::hash::pedersen([43])[0] == hash[0]); + let hash = std::hash::pedersen_commitment([state]); + assert(std::hash::pedersen_commitment([43]).x == hash.x); } diff --git a/tooling/nargo_cli/tests/execution_success/poseidon_bn254_hash/Nargo.toml b/tooling/nargo_cli/tests/execution_success/poseidon_bn254_hash/Nargo.toml index d23bb7cb919..a8e2b3d5a2c 100644 --- a/tooling/nargo_cli/tests/execution_success/poseidon_bn254_hash/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/poseidon_bn254_hash/Nargo.toml @@ -3,6 +3,5 @@ name = "poseidon_bn254_hash" description = "Poseidon 254-bit permutation test on 3 elements with alpha = 5" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/Nargo.toml b/tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/Nargo.toml index df1da360206..de4b1a44668 100644 --- a/tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/Nargo.toml @@ -3,6 +3,5 @@ name = "poseidonsponge_x5_254" description = "Variable-length Poseidon-128 sponge test on 7 elements with alpha = 5" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/src/main.nr b/tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/src/main.nr index 6d75dcccc66..910a17c8c89 100644 --- a/tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/poseidonsponge_x5_254/src/main.nr @@ -3,6 +3,6 @@ use dep::std::hash::poseidon; fn main(x: [Field; 7]) { // Test optimized sponge let result = poseidon::bn254::sponge(x); - + assert(result == 0x080ae1669d62f0197190573d4a325bfb8d8fc201ce3127cbac0c47a7ac81ac48); } diff --git a/tooling/nargo_cli/tests/execution_success/pred_eq/Nargo.toml b/tooling/nargo_cli/tests/execution_success/pred_eq/Nargo.toml index ee6f7a28e0f..b5b4a9fdf61 100644 --- a/tooling/nargo_cli/tests/execution_success/pred_eq/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/pred_eq/Nargo.toml @@ -2,6 +2,5 @@ name = "pred_eq" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/references/Nargo.toml b/tooling/nargo_cli/tests/execution_success/references/Nargo.toml index b52fdcf77f0..c4be4d4218d 100644 --- a/tooling/nargo_cli/tests/execution_success/references/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/references/Nargo.toml @@ -2,6 +2,5 @@ name = "references" type = "bin" authors = [""] -compiler_version = "0.5.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/references/src/main.nr b/tooling/nargo_cli/tests/execution_success/references/src/main.nr index 5265519f2a8..1a9be5f82b9 100644 --- a/tooling/nargo_cli/tests/execution_success/references/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/references/src/main.nr @@ -5,29 +5,20 @@ fn main(mut x: Field) { let mut s = S { y: x }; s.add2(); assert(s.y == 5); - // Regression for #1946: Method resolution error when calling &mut methods with a variable of type &mut T let s_ref = &mut s; s_ref.add2(); assert(s.y == 7); - // Test that normal mutable variables are still copied let mut a = 0; mutate_copy(a); assert(a == 0); - // Test something 3 allocations deep let mut nested_allocations = Nested { y: &mut &mut 0 }; add1(*nested_allocations.y); assert(**nested_allocations.y == 1); - // Test nested struct allocations with a mutable reference to an array. - let mut c = C { - foo: 0, - bar: &mut C2 { - array: &mut [1, 2], - }, - }; + let mut c = C { foo: 0, bar: &mut C2 { array: &mut [1, 2] } }; *c.bar.array = [3, 4]; assert(*c.bar.array == [3, 4]); @@ -75,7 +66,6 @@ impl S { fn mutate_copy(mut a: Field) { a = 7; } - // Previously the `foo.bar` in `foo.bar.mutate()` would insert an automatic dereference // of `foo` which caused the method to wrongly be mutating a copy of bar rather than the original. fn regression_1887() { @@ -92,7 +82,6 @@ impl Bar { self.x = 32; } } - // Ensure that mutating a variable does not also mutate its copy fn regression_2054() { let mut x = 2; @@ -101,7 +90,6 @@ fn regression_2054() { x += 1; assert(z == 2); } - // The compiler was still trying to convert an LValue from an array of structs to struct of arrays indexing, // even though this conversion was mostly removed elsewhere. fn regression_2030() { @@ -110,7 +98,6 @@ fn regression_2030() { let _ = *array[0]; *array[0] = 1; } - // The `mut x: &mut ...` caught a bug handling lvalues where a double-dereference would occur internally // in one step rather than being tracked by two separate steps. This lead to assigning the 1 value to the // incorrect outer `mut` reference rather than the correct `&mut` reference. @@ -135,15 +122,14 @@ fn regression_2218(x: Field, y: Field) -> Field { if x != 20 { *q1 = 10; *q2 = 2; // now we'd expect q1 == q2 == 2 - - assert(*q1 == 2); + assert(*q1 == 2); } else { *q2 = 15; assert(*q1 == 15); } } else { *q2 = 20; - assert(*q1 == 20); + assert(*q1 == 20); } // Have to assign value to return it let value = *q1; @@ -174,12 +160,11 @@ fn regression_2218_loop(x: Field, y: Field) { if x != y { *q1 = 10; *q2 = 2; // now we'd expect q1 == q2 == 2 - assert(*q1 == 2); } else { *q2 = 20; - assert(*q1 == 20); - } + assert(*q1 == 20); + } } assert(*q1 == 2); @@ -191,7 +176,6 @@ fn regression_2218_loop(x: Field, y: Field) { if x != 20 { *q1 = 10; *q2 = 2; // now we'd expect q1 == q2 == 2 - assert(*q1 == 2); } } else { @@ -206,13 +190,12 @@ fn regression_2218_loop(x: Field, y: Field) { if x != 20 { *q1 = 10; *q2 = 2; // now we'd expect q1 == q2 == 2 - assert(*q1 == 2); } } } else { *q2 = 20; - assert(*q1 == 20); + assert(*q1 == 20); } } assert(*q1 == 2); @@ -225,18 +208,16 @@ fn regression_2218_loop(x: Field, y: Field) { if x != 20 { *q1 = 10; *q2 = 2; // now we'd expect q1 == q2 == 2 - - assert(*q1 == 2); + assert(*q1 == 2); } } } } else { *q2 = 20; - assert(*q1 == 20); + assert(*q1 == 20); } assert(*q1 == 2); } - // This is more a feature test than a proper regression. // Before, we never automatically dereferenced objects in method calls to their value types. // Now, we insert as many `*` as necessary to get to `S`. diff --git a/tooling/nargo_cli/tests/execution_success/regression/Nargo.toml b/tooling/nargo_cli/tests/execution_success/regression/Nargo.toml index 91497e10342..0f6961c41d3 100644 --- a/tooling/nargo_cli/tests/execution_success/regression/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/regression/Nargo.toml @@ -2,6 +2,5 @@ name = "regression" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/regression/src/main.nr b/tooling/nargo_cli/tests/execution_success/regression/src/main.nr index 010468a450a..ed3dbf23a24 100644 --- a/tooling/nargo_cli/tests/execution_success/regression/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/regression/src/main.nr @@ -1,7 +1,7 @@ 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(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]; @@ -9,33 +9,26 @@ fn compact_decode(input: [u8; N], length: Field) -> ([u4; NIBBLE_LENGTH], Fie 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; - } - } + 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); + let out = (nibble, 2 * length + (parity as Field) - 2); out } @@ -43,30 +36,23 @@ fn compact_decode(input: [u8; N], length: Field) -> ([u4; NIBBLE_LENGTH], Fie 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 + 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 { @@ -90,20 +76,26 @@ fn bitshift_variable(idx: u64) -> u64 { 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 (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); + 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.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 + // Issue 2399 let result_0 = bitshift_literal_0(); assert(result_0 == 1); let result_4 = bitshift_literal_4(); diff --git a/tooling/nargo_cli/tests/execution_success/regression_2854/Nargo.toml b/tooling/nargo_cli/tests/execution_success/regression_2854/Nargo.toml index 33bd007d898..fb2b3c42fdd 100644 --- a/tooling/nargo_cli/tests/execution_success/regression_2854/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/regression_2854/Nargo.toml @@ -2,6 +2,5 @@ name = "regression_2854" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/regression_2854/src/main.nr b/tooling/nargo_cli/tests/execution_success/regression_2854/src/main.nr index 10ada5faeec..eccff8225b6 100644 --- a/tooling/nargo_cli/tests/execution_success/regression_2854/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/regression_2854/src/main.nr @@ -1,3 +1,3 @@ fn main(x: Field) -> pub i127 { x as i127 -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/Nargo.toml b/tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/Nargo.toml index 0361b28fd1e..93a0ba6f25a 100644 --- a/tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/Nargo.toml @@ -2,6 +2,5 @@ name = "regression_mem_op_predicate" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/src/main.nr b/tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/src/main.nr index 368ca50397f..4b5ca67f6de 100644 --- a/tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/regression_mem_op_predicate/src/main.nr @@ -1,8 +1,8 @@ fn main(mut x: [u32; 5], idx: Field) { - // We should not hit out of bounds here as we have a predicate - // that should not be hit - if idx as u32 < 3 { - x[idx] = 10; - } - assert(x[4] == 111); + // We should not hit out of bounds here as we have a predicate + // that should not be hit + if idx as u32 < 3 { + x[idx] = 10; + } + assert(x[4] == 111); } diff --git a/tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/Nargo.toml b/tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/Nargo.toml index 9d9bb35778d..aed6aa06714 100644 --- a/tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/Nargo.toml @@ -2,6 +2,5 @@ name = "regression_method_cannot_be_found" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/src/main.nr b/tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/src/main.nr index 4c1f771ae6c..1a6931a6870 100644 --- a/tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/regression_method_cannot_be_found/src/main.nr @@ -17,7 +17,7 @@ fn create(something: V) -> V { fn main() { let a = Item { id: 1 }; let b = create(a); - let _id = b.id; + let _id = b.id; // Regression for: cannot find this method b.log(); } diff --git a/tooling/nargo_cli/tests/execution_success/scalar_mul/Nargo.toml b/tooling/nargo_cli/tests/execution_success/scalar_mul/Nargo.toml index 55bf6395b34..926114ec374 100644 --- a/tooling/nargo_cli/tests/execution_success/scalar_mul/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/scalar_mul/Nargo.toml @@ -2,6 +2,5 @@ name = "scalar_mul" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] 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 index 87641b407d6..4f0a83ea9e5 100644 --- a/tooling/nargo_cli/tests/execution_success/scalar_mul/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/scalar_mul/src/main.nr @@ -1,22 +1,16 @@ 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 -) { +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; - } + 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); + assert(res[0] == pub_x); + assert(res[1] == pub_y); } diff --git a/tooling/nargo_cli/tests/execution_success/schnorr/Nargo.toml b/tooling/nargo_cli/tests/execution_success/schnorr/Nargo.toml index 3ba59b7010e..aa24a2f3caf 100644 --- a/tooling/nargo_cli/tests/execution_success/schnorr/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/schnorr/Nargo.toml @@ -2,6 +2,5 @@ name = "schnorr" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/schnorr/src/main.nr b/tooling/nargo_cli/tests/execution_success/schnorr/src/main.nr index 3c8881b2f39..d5eb92fd5f8 100644 --- a/tooling/nargo_cli/tests/execution_success/schnorr/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/schnorr/src/main.nr @@ -1,5 +1,4 @@ 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]) { @@ -12,10 +11,9 @@ fn main(message: [u8; 10], message_field: Field, pub_key_x: Field, pub_key_y: Fi // 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); + 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); + 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/tooling/nargo_cli/tests/execution_success/sha256/Nargo.toml index 97ca07f03d4..255d2156ef6 100644 --- a/tooling/nargo_cli/tests/execution_success/sha256/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/sha256/Nargo.toml @@ -2,6 +2,5 @@ name = "sha256" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/sha2_blocks/Prover.toml b/tooling/nargo_cli/tests/execution_success/sha2_blocks/Prover.toml deleted file mode 100644 index 3fe435ea07f..00000000000 --- a/tooling/nargo_cli/tests/execution_success/sha2_blocks/Prover.toml +++ /dev/null @@ -1,4 +0,0 @@ -# From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA256.pdf and https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA512.pdf -x = [0x61, 0x62, 0x63] # "abc" -result256 = [0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad] -result512 = [0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/sha2_blocks/src/main.nr b/tooling/nargo_cli/tests/execution_success/sha2_blocks/src/main.nr deleted file mode 100644 index 52891d18de2..00000000000 --- a/tooling/nargo_cli/tests/execution_success/sha2_blocks/src/main.nr +++ /dev/null @@ -1,21 +0,0 @@ -// Test Noir implementations of SHA256 and SHA512 on one- and two-block (padded) messages. -use dep::std; - -fn main(x: [u8; 3], result256: [u8; 32], result512: [u8; 64]) { - // One-block tests. - let mut digest256 = std::sha256::digest(x); - assert(digest256 == result256); - - let mut digest512 = std::sha512::digest(x); - assert(digest512 == result512); - - // Two-block SHA256 test. Taken from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA256.pdf - let y: [u8; 56] = [97,98,99,100,98,99,100,101,99,100,101,102,100,101,102,103,101,102,103,104,102,103,104,105,103,104,105,106,104,105,106,107,105,106,107,108,106,107,108,109,107,108,109,110,108,109,110,111,109,110,111,112,110,111,112,113]; // "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - digest256 = std::sha256::digest(y); - assert(digest256 == [36,141,106,97,210,6,56,184,229,192,38,147,12,62,96,57,163,60,228,89,100,255,33,103,246,236,237,212,25,219,6,193]); - - // Two-block SHA256 test. Taken from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA512.pdf - let z: [u8; 112] = [97,98,99,100,101,102,103,104,98,99,100,101,102,103,104,105,99,100,101,102,103,104,105,106,100,101,102,103,104,105,106,107,101,102,103,104,105,106,107,108,102,103,104,105,106,107,108,109,103,104,105,106,107,108,109,110,104,105,106,107,108,109,110,111,105,106,107,108,109,110,111,112,106,107,108,109,110,111,112,113,107,108,109,110,111,112,113,114,108,109,110,111,112,113,114,115,109,110,111,112,113,114,115,116,110,111,112,113,114,115,116,117]; // "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" - digest512 = std::sha512::digest(z); - assert(digest512 == [142,149,155,117,218,227,19,218,140,244,247,40,20,252,20,63,143,119,121,198,235,159,127,161,114,153,174,173,182,136,144,24,80,29,40,158,73,0,247,228,51,27,153,222,196,181,67,58,199,211,41,238,182,221,38,84,94,150,229,91,135,75,233,9]); -} diff --git a/tooling/nargo_cli/tests/execution_success/sha2_byte/Nargo.toml b/tooling/nargo_cli/tests/execution_success/sha2_byte/Nargo.toml index 849b6220db7..efd691fce58 100644 --- a/tooling/nargo_cli/tests/execution_success/sha2_byte/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/sha2_byte/Nargo.toml @@ -2,6 +2,5 @@ name = "sha2_byte" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/sha2_byte/src/main.nr b/tooling/nargo_cli/tests/execution_success/sha2_byte/src/main.nr index 6470ccd8379..fa8ddfbdf69 100644 --- a/tooling/nargo_cli/tests/execution_success/sha2_byte/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/sha2_byte/src/main.nr @@ -3,8 +3,8 @@ use dep::std; fn main(x: Field, result256: [u8; 32], result512: [u8; 64]) { let digest256 = std::sha256::digest([x as u8]); - assert(digest256 == result256); + assert(digest256 == result256); let digest512 = std::sha512::digest([x as u8]); - assert(digest512 == result512); + assert(digest512 == result512); } diff --git a/tooling/nargo_cli/tests/execution_success/signed_arithmetic/Nargo.toml b/tooling/nargo_cli/tests/execution_success/signed_arithmetic/Nargo.toml index 952e7d88a5a..47676a806e8 100644 --- a/tooling/nargo_cli/tests/execution_success/signed_arithmetic/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/signed_arithmetic/Nargo.toml @@ -2,6 +2,5 @@ name = "signed_arithmetic" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/signed_arithmetic/src/main.nr b/tooling/nargo_cli/tests/execution_success/signed_arithmetic/src/main.nr index c2a1b580f40..7a997d177ba 100644 --- a/tooling/nargo_cli/tests/execution_success/signed_arithmetic/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/signed_arithmetic/src/main.nr @@ -1,32 +1,32 @@ fn main(mut x: i32, mut y: i32, z: i32) { let mut s1: i8 = 5; let mut s2: i8 = 8; - assert(s1+s2 == 13); + assert(s1 + s2 == 13); assert(x + y == 13); s2= -8; y = -y; - assert(s1+s2 == -3); + assert(s1 + s2 == -3); assert(x + y == -3); s1 = -15; - assert(s1-s2 == -7); - assert(z-y == -7); + assert(s1 - s2 == -7); + assert(z - y == -7); s1 = -5; s2 = 8; x = -x; y = -y; - assert(s1-s2 == -13); - assert(x-y == -13); + assert(s1 - s2 == -13); + assert(x - y == -13); s2 = -8; y = -y; - assert(s1*s2 == 40); - assert(x*y == 40); + assert(s1 * s2 == 40); + assert(x * y == 40); s1 = 1; s2 = -8; - assert(s1*s2 == -8); - assert(x/x*y == -8); + assert(s1 * s2 == -8); + assert(x / x * y == -8); } diff --git a/tooling/nargo_cli/tests/execution_success/signed_division/Nargo.toml b/tooling/nargo_cli/tests/execution_success/signed_division/Nargo.toml index c1dacecae02..0d631a00b05 100644 --- a/tooling/nargo_cli/tests/execution_success/signed_division/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/signed_division/Nargo.toml @@ -2,6 +2,5 @@ name = "signed_division" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/signed_division/src/main.nr b/tooling/nargo_cli/tests/execution_success/signed_division/src/main.nr index 651df10e963..6289a2f9ed9 100644 --- a/tooling/nargo_cli/tests/execution_success/signed_division/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/signed_division/src/main.nr @@ -7,18 +7,15 @@ use dep::std; fn main(mut x: i32, mut y: i32, mut z: i32) { // 7/3 = 2 assert(x / y == z); - // -7/3 = -2 - let minus_x = std::wrapping_sub(0,x); - let minus_z = std::wrapping_sub(0,z); - let minus_y = std::wrapping_sub(0,y); - assert(x+minus_x == 0); - assert(z+minus_z == 0); + let minus_x = std::wrapping_sub(0, x); + let minus_z = std::wrapping_sub(0, z); + let minus_y = std::wrapping_sub(0, y); + assert(x + minus_x == 0); + assert(z + minus_z == 0); assert(minus_x / y == minus_z); - // -7/-3 = 2 assert(minus_x / minus_y == z); - // 7/-3 = -2 assert(x / minus_y == minus_z); } diff --git a/tooling/nargo_cli/tests/execution_success/simple_2d_array/Nargo.toml b/tooling/nargo_cli/tests/execution_success/simple_2d_array/Nargo.toml index 033c9cf1c25..b6d22d82631 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_2d_array/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/simple_2d_array/Nargo.toml @@ -2,6 +2,5 @@ name = "simple_2d_array" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/simple_2d_array/src/main.nr b/tooling/nargo_cli/tests/execution_success/simple_2d_array/src/main.nr index c098a679a3b..2ecdd4bc15f 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_2d_array/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/simple_2d_array/src/main.nr @@ -3,6 +3,6 @@ fn main(x: Field, y: Field, array_input: [[Field; 2]; 2]) { assert(array_input[0][0] == x); assert(array_input[0][1] == y); - let arr: [[Field; 2]; 1] = [[3,3]]; + let arr: [[Field; 2]; 1] = [[3, 3]]; assert_eq(arr[0], array_input[1]); } diff --git a/tooling/nargo_cli/tests/execution_success/simple_add_and_ret_arr/Nargo.toml b/tooling/nargo_cli/tests/execution_success/simple_add_and_ret_arr/Nargo.toml index 9afb8c5fd5b..6c5b0e4ca9a 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_add_and_ret_arr/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/simple_add_and_ret_arr/Nargo.toml @@ -2,6 +2,4 @@ name = "simple_add_and_ret_arr" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/simple_bitwise/Nargo.toml b/tooling/nargo_cli/tests/execution_success/simple_bitwise/Nargo.toml index c8fe1e06b4c..be425f22e5c 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_bitwise/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/simple_bitwise/Nargo.toml @@ -2,6 +2,4 @@ name = "simple_bitwise" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/simple_comparison/Nargo.toml b/tooling/nargo_cli/tests/execution_success/simple_comparison/Nargo.toml index 840eb0a7e0b..06685628444 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_comparison/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/simple_comparison/Nargo.toml @@ -2,6 +2,5 @@ name = "simple_comparison" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/simple_comparison/src/main.nr b/tooling/nargo_cli/tests/execution_success/simple_comparison/src/main.nr index f224b8a9bee..05800440459 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_comparison/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/simple_comparison/src/main.nr @@ -1,6 +1,6 @@ // Tests a very simple program. // // The features being tested is comparison -fn main(x : Field, y : Field) { +fn main(x: Field, y: Field) { assert(x as u32 < y as u32); } diff --git a/tooling/nargo_cli/tests/execution_success/simple_mut/Nargo.toml b/tooling/nargo_cli/tests/execution_success/simple_mut/Nargo.toml index b7b5c5d3dcc..c00e60bdbc0 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_mut/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/simple_mut/Nargo.toml @@ -2,6 +2,4 @@ name = "simple_mut" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/simple_mut/src/main.nr b/tooling/nargo_cli/tests/execution_success/simple_mut/src/main.nr index bba0eca5fab..d0715dbafe0 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_mut/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/simple_mut/src/main.nr @@ -1,5 +1,5 @@ // A simple program to test mutable variables -fn main(x : Field) -> pub Field { +fn main(x: Field) -> pub Field { let mut y = 2; y += x; y diff --git a/tooling/nargo_cli/tests/execution_success/simple_not/Nargo.toml b/tooling/nargo_cli/tests/execution_success/simple_not/Nargo.toml index 0ca112cf4b3..52c86b36efb 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_not/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/simple_not/Nargo.toml @@ -2,6 +2,4 @@ name = "simple_not" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/simple_not/src/main.nr b/tooling/nargo_cli/tests/execution_success/simple_not/src/main.nr index 4b17fd91eca..ba172625fe4 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_not/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/simple_not/src/main.nr @@ -1,4 +1,4 @@ // A simple program for testing the NOT op -fn main(x : bool) -> pub bool { +fn main(x: bool) -> pub bool { !x } diff --git a/tooling/nargo_cli/tests/execution_success/simple_print/Nargo.toml b/tooling/nargo_cli/tests/execution_success/simple_print/Nargo.toml index d154fbc47f2..cd8422ac482 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_print/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/simple_print/Nargo.toml @@ -2,6 +2,4 @@ name = "simple_print" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/simple_print/src/main.nr b/tooling/nargo_cli/tests/execution_success/simple_print/src/main.nr index 5f49aa548bc..6038b995af0 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_print/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/simple_print/src/main.nr @@ -2,7 +2,7 @@ // of single witnesses and witness arrays. use dep::std; -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { std::println(x); std::println([x, y]); } diff --git a/tooling/nargo_cli/tests/execution_success/simple_program_addition/Nargo.toml b/tooling/nargo_cli/tests/execution_success/simple_program_addition/Nargo.toml index 8cf28eb45a7..28967a28a55 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_program_addition/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/simple_program_addition/Nargo.toml @@ -2,6 +2,5 @@ name = "simple_program_addition" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/simple_program_addition/src/main.nr b/tooling/nargo_cli/tests/execution_success/simple_program_addition/src/main.nr index 082d9b5071f..0390d79e83b 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_program_addition/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/simple_program_addition/src/main.nr @@ -1,5 +1,5 @@ // The feature being tested is handling of // a binary operation. -fn main(x : Field) -> pub Field { +fn main(x: Field) -> pub Field { x + 1 } diff --git a/tooling/nargo_cli/tests/execution_success/simple_radix/Nargo.toml b/tooling/nargo_cli/tests/execution_success/simple_radix/Nargo.toml index 6c208c1645c..12cbc8da1d3 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_radix/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/simple_radix/Nargo.toml @@ -2,6 +2,4 @@ name = "simple_radix" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/simple_radix/src/main.nr b/tooling/nargo_cli/tests/execution_success/simple_radix/src/main.nr index 67268a932a3..4a335e1bade 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_radix/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/simple_radix/src/main.nr @@ -1,5 +1,5 @@ // Simple program to test to_radix -fn main(x : Field) { +fn main(x: Field) { let bits = x.to_le_bits(3); assert(bits[0] == 0); assert(bits[1] == 1); diff --git a/tooling/nargo_cli/tests/execution_success/simple_shield/Nargo.toml b/tooling/nargo_cli/tests/execution_success/simple_shield/Nargo.toml index b710f38d826..7e9579b0af4 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_shield/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/simple_shield/Nargo.toml @@ -2,6 +2,5 @@ name = "simple_shield" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/simple_shield/Prover.toml b/tooling/nargo_cli/tests/execution_success/simple_shield/Prover.toml index 55492a9bf6d..7878e4b8281 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_shield/Prover.toml +++ b/tooling/nargo_cli/tests/execution_success/simple_shield/Prover.toml @@ -1,6 +1,6 @@ # Random test key priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" -note_root = "0x0f8cd7b45fbb4e08f63126f1673ce9e574cfbda70f36c2e5182f9e3dbe6524c0" +note_root = "0x02278fc806225cd696bd502049f7bb98624536de56d09343f8a26ac1876b23a0" index = "0" note_hash_path = [ "0x1cdcf02431ba623767fe389337d011df1048dcc24b98ed81cec97627bab454a0", diff --git a/tooling/nargo_cli/tests/execution_success/simple_shield/src/main.nr b/tooling/nargo_cli/tests/execution_success/simple_shield/src/main.nr index c26a53d56cd..c46d3b4594c 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_shield/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/simple_shield/src/main.nr @@ -1,35 +1,29 @@ use dep::std; fn main( - // Public key of note + // Public key of note // all notes have the same denomination - priv_key: Field, - - // Merkle membership proof - note_root: pub Field, - index: Field, - note_hash_path: [Field; 3], - - // Receiver public key - to_pubkey_x: Field, - to_pubkey_y: Field, + priv_key: Field, + // Merkle membership proof + note_root: pub Field, + index: Field, + note_hash_path: [Field; 3], + // Receiver public key + to_pubkey_x: Field, + to_pubkey_y: Field ) -> pub [Field; 2] { // Compute public key from private key to show ownership let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key, 0); let pubkey_x = pubkey[0]; let pubkey_y = pubkey[1]; - // Compute input note commitment - let note_commitment = std::hash::pedersen([pubkey_x, pubkey_y]); - + let note_commitment = std::hash::pedersen_commitment([pubkey_x, pubkey_y]); // Compute input note nullifier - let nullifier = std::hash::pedersen([note_commitment[0], index, priv_key]); - + let nullifier = std::hash::pedersen_commitment([note_commitment.x, index, priv_key]); // Compute output note nullifier - let receiver_note_commitment = std::hash::pedersen([to_pubkey_x, to_pubkey_y]); - + let receiver_note_commitment = std::hash::pedersen_commitment([to_pubkey_x, to_pubkey_y]); // Check that the input note nullifier is in the root - assert(note_root == std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path)); + assert(note_root == std::merkle::compute_merkle_root(note_commitment.x, index, note_hash_path)); - [nullifier[0], receiver_note_commitment[0]] + [nullifier.x, receiver_note_commitment.x] } diff --git a/tooling/nargo_cli/tests/execution_success/simple_shift_left_right/Nargo.toml b/tooling/nargo_cli/tests/execution_success/simple_shift_left_right/Nargo.toml index 09eb46d547e..2e75d5feada 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_shift_left_right/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/simple_shift_left_right/Nargo.toml @@ -2,6 +2,5 @@ name = "simple_shift_left_right" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/simple_shift_left_right/src/main.nr b/tooling/nargo_cli/tests/execution_success/simple_shift_left_right/src/main.nr index 517ef429458..40698af6ce7 100644 --- a/tooling/nargo_cli/tests/execution_success/simple_shift_left_right/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/simple_shift_left_right/src/main.nr @@ -1,7 +1,7 @@ // Tests a very simple program. // // The features being tested are left and right shifts. -fn main(x : u32) { +fn main(x: u32) { let z = x >> 4; let t = x << 4; assert(z == t >> 8); diff --git a/tooling/nargo_cli/tests/execution_success/slice_dynamic_index/Nargo.toml b/tooling/nargo_cli/tests/execution_success/slice_dynamic_index/Nargo.toml index 08322784151..a02faeae27a 100644 --- a/tooling/nargo_cli/tests/execution_success/slice_dynamic_index/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/slice_dynamic_index/Nargo.toml @@ -2,6 +2,5 @@ name = "slice_dynamic_index" type = "bin" authors = [""] -compiler_version = "0.10.3" [dependencies] \ No newline at end of file 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 index 3f3177b1b5a..2e5c0122dfb 100644 --- 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 @@ -1,4 +1,4 @@ -fn main(x : Field) { +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); } @@ -57,7 +57,6 @@ fn dynamic_slice_index_set_else(mut slice: [Field], x: Field, y: Field) { } 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) { @@ -79,7 +78,6 @@ fn dynamic_array_index_if(mut array: [Field; 5], x: Field) { } 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) { @@ -125,13 +123,11 @@ fn dynamic_slice_merge_if(mut slice: [Field], x: Field) { 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 @@ -237,7 +233,7 @@ fn dynamic_slice_merge_two_ifs(mut slice: [Field], x: Field) { if x == 20 { slice = slice.push_back(20); - } + } slice = slice.push_back(15); diff --git a/tooling/nargo_cli/tests/execution_success/slice_struct_field/Nargo.toml b/tooling/nargo_cli/tests/execution_success/slice_struct_field/Nargo.toml new file mode 100644 index 00000000000..9530ebf9271 --- /dev/null +++ b/tooling/nargo_cli/tests/execution_success/slice_struct_field/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "slice_struct_field" +type = "bin" +authors = [""] + +[dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/slice_struct_field/Prover.toml b/tooling/nargo_cli/tests/execution_success/slice_struct_field/Prover.toml new file mode 100644 index 00000000000..7127baac5bf --- /dev/null +++ b/tooling/nargo_cli/tests/execution_success/slice_struct_field/Prover.toml @@ -0,0 +1 @@ +y = "3" 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 new file mode 100644 index 00000000000..c00fdf85180 --- /dev/null +++ b/tooling/nargo_cli/tests/execution_success/slice_struct_field/src/main.nr @@ -0,0 +1,177 @@ +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/slices/Nargo.toml b/tooling/nargo_cli/tests/execution_success/slices/Nargo.toml index bc9dcc7729a..3eec413bc07 100644 --- a/tooling/nargo_cli/tests/execution_success/slices/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/slices/Nargo.toml @@ -2,6 +2,4 @@ name = "slices" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/slices/src/main.nr b/tooling/nargo_cli/tests/execution_success/slices/src/main.nr index 8d53e013f96..c377d2e5b2f 100644 --- a/tooling/nargo_cli/tests/execution_success/slices/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/slices/src/main.nr @@ -1,7 +1,7 @@ use dep::std::slice; use dep::std; -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { let mut slice = [0; 2]; assert(slice[0] == 0); assert(slice[0] != 1); @@ -51,7 +51,6 @@ fn main(x : Field, y : pub Field) { regression_merge_slices(x, y); regression_2370(); } - // Ensure that slices of struct/tuple values work. fn regression_2083() { let y = [(1, 2)]; @@ -61,7 +60,6 @@ fn regression_2083() { let y = y.push_front((10, 11)); // [(10, 11), (1, 2), (3, 4), (5, 6)] let y = y.push_front((12, 13)); // [(12, 13), (10, 11), (1, 2), (3, 4), (5, 6)] - assert(y[1].0 == 10); let y = y.insert(1, (55, 56)); // [(12, 13), (55, 56), (10, 11), (1, 2), (3, 4), (5, 6)] @@ -84,7 +82,6 @@ fn regression_2083() { assert(x.0 == 5); assert(x.1 == 6); } - // The parameters to this function must come from witness values (inputs to main) fn regression_merge_slices(x: Field, y: Field) { merge_slices_if(x, y); @@ -145,21 +142,15 @@ fn merge_slices_else(x: Field) { assert(slice[2] == 5); assert(slice.len() == 3); } - // Test returning a merged slice without a mutation fn merge_slices_return(x: Field, y: Field) -> [Field] { let slice = [0; 2]; if x != y { - if x != 20 { - slice.push_back(y) - } else { - slice - } + if x != 20 { slice.push_back(y) } else { slice } } else { slice } } - // Test mutating a slice inside of an if statement fn merge_slices_mutate(x: Field, y: Field) -> [Field] { let mut slice = [0; 2]; @@ -171,7 +162,6 @@ fn merge_slices_mutate(x: Field, y: Field) -> [Field] { } slice } - // Test mutating a slice inside of a loop in an if statement fn merge_slices_mutate_in_loop(x: Field, y: Field) -> [Field] { let mut slice = [0; 2]; @@ -196,7 +186,7 @@ fn merge_slices_mutate_two_ifs(x: Field, y: Field) -> [Field] { if x == 20 { slice = slice.push_back(20); - } + } slice = slice.push_back(15); slice = slice.push_back(30); @@ -271,7 +261,6 @@ fn merge_slices_push_then_insert(x: Field, y: Field) -> [Field] { } slice = slice.insert(1, 50); - // Test that we can use slice insert the same as slice push back slice = slice.insert(6, 100); @@ -302,7 +291,6 @@ fn merge_slices_remove_between_ifs(x: Field, y: Field) -> [Field] { slice } - // Previously, we'd get a type error when trying to assign an array of a different size to // an existing array variable. Now, we infer the variable must be a slice. fn regression_2370() { diff --git a/tooling/nargo_cli/tests/execution_success/strings/Nargo.toml b/tooling/nargo_cli/tests/execution_success/strings/Nargo.toml index 30df1a2f27e..76a9beb6909 100644 --- a/tooling/nargo_cli/tests/execution_success/strings/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/strings/Nargo.toml @@ -2,6 +2,5 @@ name = "strings" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/strings/src/main.nr b/tooling/nargo_cli/tests/execution_success/strings/src/main.nr index 02e2fa678cd..cb2218837f3 100644 --- a/tooling/nargo_cli/tests/execution_success/strings/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/strings/src/main.nr @@ -1,9 +1,8 @@ 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) { +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"); @@ -23,9 +22,9 @@ fn main(message : pub str<11>, y : Field, hex_as_string : str<4>, hex_as_field : std::println(bad_message); assert(message != bad_message); - let hash = std::hash::pedersen([x]); + 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); @@ -48,7 +47,7 @@ fn test_prints_array() { std::println(array); - let hash = std::hash::pedersen(array); + let hash = std::hash::pedersen_commitment(array); std::println(hash); } diff --git a/tooling/nargo_cli/tests/execution_success/struct/Nargo.toml b/tooling/nargo_cli/tests/execution_success/struct/Nargo.toml index 34c3d838538..6622edd0653 100644 --- a/tooling/nargo_cli/tests/execution_success/struct/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/struct/Nargo.toml @@ -2,6 +2,5 @@ name = "struct" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/struct/src/main.nr b/tooling/nargo_cli/tests/execution_success/struct/src/main.nr index 2bd5a1aec28..45c5e347e5a 100644 --- a/tooling/nargo_cli/tests/execution_success/struct/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/struct/src/main.nr @@ -33,12 +33,8 @@ struct MyStruct { my_int: u32, my_nest: Nested, } -fn test_struct_in_tuple(a_bool : bool,x:Field, y:Field) -> (MyStruct, bool) { - let my_struct = MyStruct { - my_bool: a_bool, - my_int: 5, - my_nest: Nested{a:x,b:y}, - }; +fn test_struct_in_tuple(a_bool: bool, x: Field, y: Field) -> (MyStruct, bool) { + let my_struct = MyStruct { my_bool: a_bool, my_int: 5, my_nest: Nested { a: x, b: y } }; (my_struct, a_bool) } @@ -57,20 +53,18 @@ struct Unit; fn main(x: Field, y: Field) { let unit = Unit {}; - let first = Foo::default(x,y); + let first = Foo::default(x, y); let p = Pair { first, second: 1 }; assert(p.bar() == x); assert(p.second == y); assert(p.first.array[0] != p.first.array[1]); - // Nested structs - let (struct_from_tuple, a_bool) = test_struct_in_tuple(true,x,y); + let (struct_from_tuple, a_bool) = test_struct_in_tuple(true, x, y); assert(struct_from_tuple.my_bool == true); assert(a_bool == true); assert(struct_from_tuple.my_int == 5); assert(struct_from_tuple.my_nest.a == 0); - // Regression test for issue #670 let Animal { legs, eyes } = get_dog(); let six = legs + eyes as Field; diff --git a/tooling/nargo_cli/tests/execution_success/struct_array_inputs/Nargo.toml b/tooling/nargo_cli/tests/execution_success/struct_array_inputs/Nargo.toml index 7be5ccbb99f..40160fb397f 100644 --- a/tooling/nargo_cli/tests/execution_success/struct_array_inputs/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/struct_array_inputs/Nargo.toml @@ -2,6 +2,4 @@ name = "struct_array_inputs" type = "bin" authors = [""] -compiler_version = "0.6.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/struct_fields_ordering/Nargo.toml b/tooling/nargo_cli/tests/execution_success/struct_fields_ordering/Nargo.toml index 2e886f62689..767f51acda3 100644 --- a/tooling/nargo_cli/tests/execution_success/struct_fields_ordering/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/struct_fields_ordering/Nargo.toml @@ -2,6 +2,5 @@ name = "struct_fields_ordering" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/struct_fields_ordering/src/main.nr b/tooling/nargo_cli/tests/execution_success/struct_fields_ordering/src/main.nr index 5d4aa7c5a1e..1a2e2d462e2 100644 --- a/tooling/nargo_cli/tests/execution_success/struct_fields_ordering/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/struct_fields_ordering/src/main.nr @@ -5,7 +5,7 @@ struct myStruct { bar: Field, } -fn main(y : pub myStruct) { +fn main(y: pub myStruct) { assert(y.foo == 5); assert(y.bar == 7); } diff --git a/tooling/nargo_cli/tests/execution_success/struct_inputs/Nargo.toml b/tooling/nargo_cli/tests/execution_success/struct_inputs/Nargo.toml index 455a7b28ddb..7dd6f78b750 100644 --- a/tooling/nargo_cli/tests/execution_success/struct_inputs/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/struct_inputs/Nargo.toml @@ -2,6 +2,5 @@ name = "struct_inputs" type = "bin" authors = [""] -compiler_version = "0.1" [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/struct_inputs/src/main.nr b/tooling/nargo_cli/tests/execution_success/struct_inputs/src/main.nr index 96684d01a1d..5b03483cbaf 100644 --- a/tooling/nargo_cli/tests/execution_success/struct_inputs/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/struct_inputs/src/main.nr @@ -6,12 +6,12 @@ struct myStruct { message: str<5>, } -fn main(x : Field, y : pub myStruct, z: pub foo::bar::barStruct, a: pub foo::fooStruct) -> pub Field { +fn main(x: Field, y: pub myStruct, z: pub foo::bar::barStruct, a: pub foo::fooStruct) -> pub Field { let struct_from_bar = foo::bar::barStruct { val: 1, array: [0, 1], message: "hello" }; check_inner_struct(a, z); - for i in 0 .. struct_from_bar.array.len() { + for i in 0..struct_from_bar.array.len() { assert(struct_from_bar.array[i] == z.array[i]); } assert(z.val == struct_from_bar.val); @@ -28,7 +28,7 @@ fn main(x : Field, y : pub myStruct, z: pub foo::bar::barStruct, a: pub foo::foo fn check_inner_struct(a: foo::fooStruct, z: foo::bar::barStruct) { assert(a.bar_struct.val == z.val); - for i in 0.. a.bar_struct.array.len() { + for i in 0..a.bar_struct.array.len() { assert(a.bar_struct.array[i] == z.array[i]); } } diff --git a/tooling/nargo_cli/tests/execution_success/submodules/Nargo.toml b/tooling/nargo_cli/tests/execution_success/submodules/Nargo.toml index a98eda3cd89..082afdf3f10 100644 --- a/tooling/nargo_cli/tests/execution_success/submodules/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/submodules/Nargo.toml @@ -2,6 +2,4 @@ name = "submodules" type = "bin" authors = [""] -compiler_version = "0.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/to_be_bytes/Nargo.toml b/tooling/nargo_cli/tests/execution_success/to_be_bytes/Nargo.toml index c0837a335f8..e9d2e30b4c4 100644 --- a/tooling/nargo_cli/tests/execution_success/to_be_bytes/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/to_be_bytes/Nargo.toml @@ -2,6 +2,4 @@ name = "to_be_bytes" type = "bin" authors = [""] -compiler_version = "0.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/to_be_bytes/src/main.nr b/tooling/nargo_cli/tests/execution_success/to_be_bytes/src/main.nr index 81b08ed1785..64d54ddff66 100644 --- a/tooling/nargo_cli/tests/execution_success/to_be_bytes/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/to_be_bytes/src/main.nr @@ -1,12 +1,12 @@ -fn main(x : Field) -> pub [u8; 31] { +fn main(x: Field) -> pub [u8; 31] { // The result of this byte array will be big-endian let byte_array = x.to_be_bytes(31); let mut bytes = [0; 31]; for i in 0..31 { bytes[i] = byte_array[i]; } - if ( bytes[30] != 60) | (bytes[29] != 33) | (bytes[28] != 31) { - assert(false); + if (bytes[30] != 60) | (bytes[29] != 33) | (bytes[28] != 31) { + assert(false); } bytes } diff --git a/tooling/nargo_cli/tests/execution_success/to_bytes_consistent/Nargo.toml b/tooling/nargo_cli/tests/execution_success/to_bytes_consistent/Nargo.toml index 65f95d159c8..1e117b83883 100644 --- a/tooling/nargo_cli/tests/execution_success/to_bytes_consistent/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/to_bytes_consistent/Nargo.toml @@ -2,6 +2,4 @@ name = "to_bytes_consistent" type = "bin" authors = [""] -compiler_version = "0.10.3" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/to_bytes_consistent/src/main.nr b/tooling/nargo_cli/tests/execution_success/to_bytes_consistent/src/main.nr index 270491e132d..638b34c9bab 100644 --- a/tooling/nargo_cli/tests/execution_success/to_bytes_consistent/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/to_bytes_consistent/src/main.nr @@ -1,9 +1,8 @@ // This test aims to check that we have consistent behavior // between a `to_be_bytes` call (which is radix decomposition under the hood) // with constant inputs or with witness inputs. - // x = 2040124 -fn main(x : Field) { +fn main(x: Field) { let byte_array = x.to_be_bytes(31); let x_as_constant = 2040124; let constant_byte_array = x_as_constant.to_be_bytes(31); diff --git a/tooling/nargo_cli/tests/execution_success/to_bytes_integration/Nargo.toml b/tooling/nargo_cli/tests/execution_success/to_bytes_integration/Nargo.toml index fd1c714b123..c89c32eb06c 100644 --- a/tooling/nargo_cli/tests/execution_success/to_bytes_integration/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/to_bytes_integration/Nargo.toml @@ -2,6 +2,4 @@ name = "to_bytes_integration" type = "bin" authors = [""] -compiler_version = "0.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/to_bytes_integration/src/main.nr b/tooling/nargo_cli/tests/execution_success/to_bytes_integration/src/main.nr index 43a35f05488..3c43caf1806 100644 --- a/tooling/nargo_cli/tests/execution_success/to_bytes_integration/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/to_bytes_integration/src/main.nr @@ -1,10 +1,10 @@ use dep::std; -fn main(x : Field, a: Field) { +fn main(x: Field, a: Field) { let y: Field = 2040124; let be_byte_array = y.to_be_bytes(31); let le_byte_array = x.to_le_bytes(31); - + assert(le_byte_array[0] == 60); assert(le_byte_array[0] == be_byte_array[30]); assert(le_byte_array[1] == be_byte_array[29]); diff --git a/tooling/nargo_cli/tests/execution_success/to_le_bytes/Nargo.toml b/tooling/nargo_cli/tests/execution_success/to_le_bytes/Nargo.toml index 34cf8a5afc7..3d02c3510fd 100644 --- a/tooling/nargo_cli/tests/execution_success/to_le_bytes/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/to_le_bytes/Nargo.toml @@ -2,6 +2,4 @@ name = "to_le_bytes" type = "bin" authors = [""] -compiler_version = "0.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/to_le_bytes/src/main.nr b/tooling/nargo_cli/tests/execution_success/to_le_bytes/src/main.nr index 7155122b372..05eefc0f143 100644 --- a/tooling/nargo_cli/tests/execution_success/to_le_bytes/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/to_le_bytes/src/main.nr @@ -1,4 +1,4 @@ -fn main(x : Field) -> pub [u8; 31] { +fn main(x: Field) -> pub [u8; 31] { // The result of this byte array will be little-endian let byte_array = x.to_le_bytes(31); assert(byte_array.len() == 31); diff --git a/tooling/nargo_cli/tests/execution_success/trait_as_return_type/Nargo.toml b/tooling/nargo_cli/tests/execution_success/trait_as_return_type/Nargo.toml index 1a7ef7ee8a2..afd89f0c3a1 100644 --- a/tooling/nargo_cli/tests/execution_success/trait_as_return_type/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/trait_as_return_type/Nargo.toml @@ -2,6 +2,4 @@ name = "trait_as_return_type" type = "bin" authors = [""] -compiler_version = "0.10.5" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/trait_as_return_type/src/main.nr b/tooling/nargo_cli/tests/execution_success/trait_as_return_type/src/main.nr index e84fe15aba7..f6828a356c1 100644 --- a/tooling/nargo_cli/tests/execution_success/trait_as_return_type/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/trait_as_return_type/src/main.nr @@ -8,7 +8,6 @@ struct C { x: Field } - impl SomeTrait for A { fn magic_number(self) -> Field { 2 @@ -27,8 +26,6 @@ impl SomeTrait for C { } } - - fn factory_a() -> impl SomeTrait { A {} } @@ -38,9 +35,8 @@ fn factory_b() -> impl SomeTrait { } fn factory_c(x: Field) -> impl SomeTrait { - C {x:x} + C { x } } - // x = 15 fn main(x: u32) { let a = factory_a(); @@ -52,4 +48,4 @@ fn main(x: u32) { let c = factory_c(10); assert(c.magic_number() == 10); assert(factory_c(13).magic_number() == 13); -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/execution_success/trait_impl_base_type/Nargo.toml b/tooling/nargo_cli/tests/execution_success/trait_impl_base_type/Nargo.toml index dad2ca8fed2..845498737c1 100644 --- a/tooling/nargo_cli/tests/execution_success/trait_impl_base_type/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/trait_impl_base_type/Nargo.toml @@ -2,6 +2,4 @@ name = "trait_impl_base_type" type = "bin" authors = [""] -compiler_version = "0.10.5" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/trait_impl_base_type/src/main.nr b/tooling/nargo_cli/tests/execution_success/trait_impl_base_type/src/main.nr index 47e919cf39c..bb11dcab73a 100644 --- a/tooling/nargo_cli/tests/execution_success/trait_impl_base_type/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/trait_impl_base_type/src/main.nr @@ -9,7 +9,6 @@ impl Fieldable for u32 { } } - impl Fieldable for [u32; 3] { fn to_field(self) -> Field { let res = self[0] + self[1] + self[2]; @@ -80,33 +79,11 @@ fn some_func(x: u32) -> u32 { x * 2 - 3 } - -trait MutFieldable { - fn mut_to_field(self) -> Field; -} - -impl MutFieldable for &mut u64 { - fn mut_to_field(self) -> Field { - 1337 as Field - } -} - -fn a(y: &mut u64) -> Field { - y.mut_to_field() -} - -impl Fieldable for &mut u64 { - fn to_field(self) -> Field { - 777 as Field - } -} - impl Fieldable for u64 { fn to_field(self) -> Field { 66 as Field } } - // x = 15 fn main(x: u32) { assert(x.to_field() == 15); @@ -134,8 +111,5 @@ fn main(x: u32) { assert(some_func.to_field() == 17); let mut y = 0 as u64; - assert(a(&mut y) == 1337); - assert((&mut y).mut_to_field() == 1337); - assert((&mut y).to_field() == 777); assert(y.to_field() == 66); -} \ No newline at end of file +} diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/Nargo.toml b/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/Nargo.toml index a13ed98b632..555c3b38b98 100644 --- a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/Nargo.toml @@ -2,8 +2,6 @@ name = "traits_in_crates_1" type = "bin" authors = [""] -compiler_version = "0.12.0" - [dependencies] crate1 = { path = "crate1" } crate2 = { path = "crate2" } diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate1/Nargo.toml b/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate1/Nargo.toml index 0a94742b76a..f49603ba203 100644 --- a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate1/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate1/Nargo.toml @@ -2,7 +2,5 @@ name = "crate1" type = "lib" authors = [""] -compiler_version = "0.12.0" - [dependencies] crate2 = { path = "../crate2" } diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate2/Nargo.toml b/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate2/Nargo.toml index a90a5dcceea..c86c5edf51a 100644 --- a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate2/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/crate2/Nargo.toml @@ -2,6 +2,4 @@ name = "crate2" type = "lib" authors = [""] -compiler_version = "0.12.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/src/main.nr b/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/src/main.nr index cb6416f7732..7ba2f63c5c0 100644 --- a/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/traits_in_crates_1/src/main.nr @@ -1,4 +1,4 @@ -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { let mut V = dep::crate2::MyStruct { Q: x }; V.Add10(); assert(V.Q == y); diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/Nargo.toml b/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/Nargo.toml index 8b5bc49e0bb..11a86a08402 100644 --- a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/Nargo.toml @@ -2,8 +2,6 @@ name = "traits_in_crates_2" type = "bin" authors = [""] -compiler_version = "0.12.0" - [dependencies] crate1 = { path = "crate1" } crate2 = { path = "crate2" } diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate1/Nargo.toml b/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate1/Nargo.toml index b28e0e840c4..de1eddf2cf0 100644 --- a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate1/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate1/Nargo.toml @@ -2,6 +2,4 @@ name = "crate1" type = "lib" authors = [""] -compiler_version = "0.12.0" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate2/Nargo.toml b/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate2/Nargo.toml index 51c201372ee..885d41f0a27 100644 --- a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate2/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/crate2/Nargo.toml @@ -2,7 +2,5 @@ name = "crate2" type = "lib" authors = [""] -compiler_version = "0.12.0" - [dependencies] crate1 = { path = "../crate1" } diff --git a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/src/main.nr b/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/src/main.nr index cb6416f7732..7ba2f63c5c0 100644 --- a/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/traits_in_crates_2/src/main.nr @@ -1,4 +1,4 @@ -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { let mut V = dep::crate2::MyStruct { Q: x }; V.Add10(); assert(V.Q == y); diff --git a/tooling/nargo_cli/tests/execution_success/tuple_inputs/Nargo.toml b/tooling/nargo_cli/tests/execution_success/tuple_inputs/Nargo.toml index 7cc7bc85393..f4af6cfe6e3 100644 --- a/tooling/nargo_cli/tests/execution_success/tuple_inputs/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/tuple_inputs/Nargo.toml @@ -2,6 +2,4 @@ name = "tuple_inputs" type = "bin" authors = [""] -compiler_version = "0.14.1" - [dependencies] \ No newline at end of file diff --git a/tooling/nargo_cli/tests/execution_success/tuple_inputs/src/main.nr b/tooling/nargo_cli/tests/execution_success/tuple_inputs/src/main.nr index 2fc44a8fc75..38fec58f14f 100644 --- a/tooling/nargo_cli/tests/execution_success/tuple_inputs/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/tuple_inputs/src/main.nr @@ -8,7 +8,7 @@ struct Foo { bar: Bar, } -fn main(pair : (Field, Field), x: [(u8, u8, u8); 2], struct_pair: (Foo, Bar)) -> pub (Field, u8) { +fn main(pair: (Field, Field), x: [(u8, u8, u8); 2], struct_pair: (Foo, Bar)) -> pub (Field, u8) { let mut start_val = 0; for i in 0..2 { assert(x[i].0 == start_val); @@ -27,6 +27,7 @@ fn main(pair : (Field, Field), x: [(u8, u8, u8); 2], struct_pair: (Foo, Bar)) -> } else { (pair.0 + 1, pair.0) }; + assert(u == pair.0 + 1); assert(v == pair.0); diff --git a/tooling/nargo_cli/tests/execution_success/tuples/Nargo.toml b/tooling/nargo_cli/tests/execution_success/tuples/Nargo.toml index 54603e9a96b..f6ed9f1e649 100644 --- a/tooling/nargo_cli/tests/execution_success/tuples/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/tuples/Nargo.toml @@ -2,6 +2,4 @@ name = "tuples" type = "bin" authors = [""] -compiler_version = "0.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/tuples/src/main.nr b/tooling/nargo_cli/tests/execution_success/tuples/src/main.nr index e836c66a0fa..5526fcad422 100644 --- a/tooling/nargo_cli/tests/execution_success/tuples/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/tuples/src/main.nr @@ -7,14 +7,9 @@ fn main(x: Field, y: Field) { assert(a == 0); assert(b == 1); - let (u, v) = if x as u32 < 1 { - (x, x + 1) - } else { - (x + 1, x) - }; - assert(u == x+1); + let (u, v) = if x as u32 < 1 { (x, x + 1) } else { (x + 1, x) }; + assert(u == x + 1); assert(v == x); - // Test mutating tuples let mut mutable = ((0, 0), 1, 2, 3); mutable.0 = (x, y); diff --git a/tooling/nargo_cli/tests/execution_success/type_aliases/Nargo.toml b/tooling/nargo_cli/tests/execution_success/type_aliases/Nargo.toml index e828f6913e0..a12df601a91 100644 --- a/tooling/nargo_cli/tests/execution_success/type_aliases/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/type_aliases/Nargo.toml @@ -2,6 +2,4 @@ name = "type_aliases" type = "bin" authors = [""] -compiler_version = "0.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/type_aliases/src/main.nr b/tooling/nargo_cli/tests/execution_success/type_aliases/src/main.nr index 573a501367f..ee62b0b7260 100644 --- a/tooling/nargo_cli/tests/execution_success/type_aliases/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/type_aliases/src/main.nr @@ -10,7 +10,7 @@ struct MyStruct { foo: Bar, } -fn main(x : [Field; 2]) { +fn main(x: [Field; 2]) { let a: Foo = [1, 2]; assert(a[0] != x[0]); @@ -22,14 +22,11 @@ fn main(x : [Field; 2]) { let e: Three = (c, d); assert(e.0 == 1); - let s = MyStruct { - foo: 10 - }; + let s = MyStruct { foo: 10 }; assert(s.foo == 10); let _regression2502: Regression2502Alias = Regression2502 {}; } - // An ICE was occurring if a type alias referred to a struct before it was initialized // during name resolution. The fix was to initialize structs during def collection instead. type Regression2502Alias = Regression2502; diff --git a/tooling/nargo_cli/tests/execution_success/workspace/crates/a/Nargo.toml b/tooling/nargo_cli/tests/execution_success/workspace/crates/a/Nargo.toml index 411f048a93b..8d0e1aca4a9 100644 --- a/tooling/nargo_cli/tests/execution_success/workspace/crates/a/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/workspace/crates/a/Nargo.toml @@ -2,6 +2,4 @@ name = "a" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/workspace/crates/a/src/main.nr b/tooling/nargo_cli/tests/execution_success/workspace/crates/a/src/main.nr index 550e5034a7b..cf72627da2e 100644 --- a/tooling/nargo_cli/tests/execution_success/workspace/crates/a/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/workspace/crates/a/src/main.nr @@ -1,3 +1,3 @@ -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { assert(x == y); } diff --git a/tooling/nargo_cli/tests/execution_success/workspace/crates/b/Nargo.toml b/tooling/nargo_cli/tests/execution_success/workspace/crates/b/Nargo.toml index 1af8ef961cc..f316511340f 100644 --- a/tooling/nargo_cli/tests/execution_success/workspace/crates/b/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/workspace/crates/b/Nargo.toml @@ -2,6 +2,4 @@ name = "b" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/workspace/crates/b/src/main.nr b/tooling/nargo_cli/tests/execution_success/workspace/crates/b/src/main.nr index 6e170de75fc..4e1fd3c9035 100644 --- a/tooling/nargo_cli/tests/execution_success/workspace/crates/b/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/workspace/crates/b/src/main.nr @@ -1,3 +1,3 @@ -fn main(x : Field, y : pub Field) { +fn main(x: Field, y: pub Field) { assert(x != y); } diff --git a/tooling/nargo_cli/tests/execution_success/workspace_default_member/a/Nargo.toml b/tooling/nargo_cli/tests/execution_success/workspace_default_member/a/Nargo.toml index 411f048a93b..8d0e1aca4a9 100644 --- a/tooling/nargo_cli/tests/execution_success/workspace_default_member/a/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/workspace_default_member/a/Nargo.toml @@ -2,6 +2,4 @@ name = "a" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/workspace_default_member/a/src/main.nr b/tooling/nargo_cli/tests/execution_success/workspace_default_member/a/src/main.nr index 550e5034a7b..cf72627da2e 100644 --- a/tooling/nargo_cli/tests/execution_success/workspace_default_member/a/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/workspace_default_member/a/src/main.nr @@ -1,3 +1,3 @@ -fn main(x : Field, y : pub Field) { +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/tooling/nargo_cli/tests/execution_success/workspace_default_member/b/Nargo.toml index 1af8ef961cc..f316511340f 100644 --- a/tooling/nargo_cli/tests/execution_success/workspace_default_member/b/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/workspace_default_member/b/Nargo.toml @@ -2,6 +2,4 @@ name = "b" type = "bin" authors = [""] -compiler_version = "0.8.0" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/xor/Nargo.toml b/tooling/nargo_cli/tests/execution_success/xor/Nargo.toml index ea15f5eb6c5..ddf3b6d86c5 100644 --- a/tooling/nargo_cli/tests/execution_success/xor/Nargo.toml +++ b/tooling/nargo_cli/tests/execution_success/xor/Nargo.toml @@ -2,6 +2,4 @@ name = "xor" type = "bin" authors = [""] -compiler_version = "0.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/execution_success/xor/src/main.nr b/tooling/nargo_cli/tests/execution_success/xor/src/main.nr index d4261aa786a..4ceef1b518f 100644 --- a/tooling/nargo_cli/tests/execution_success/xor/src/main.nr +++ b/tooling/nargo_cli/tests/execution_success/xor/src/main.nr @@ -1,4 +1,4 @@ -fn main(x : u32, y : pub u32) { +fn main(x: u32, y: pub u32) { let m = x ^ y; assert(m != 10); diff --git a/tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/Nargo.toml b/tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/Nargo.toml index dd56e682004..3d2cf2c6096 100644 --- a/tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/Nargo.toml +++ b/tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/Nargo.toml @@ -2,6 +2,4 @@ name = "should_fail_with_mismatch" type = "bin" authors = [""] -compiler_version = "0.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/src/main.nr b/tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/src/main.nr index b2672221c34..a677b10b0cd 100644 --- a/tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/src/main.nr +++ b/tooling/nargo_cli/tests/noir_test_failure/should_fail_mismatch/src/main.nr @@ -1,17 +1,14 @@ - #[test(should_fail_with = "Not equal")] fn test_different_string() { assert_eq(0, 1, "Different string"); } - // The assert message has a space #[test(should_fail_with = "Not equal")] fn test_with_extra_space() { assert_eq(0, 1, "Not equal "); } - // The assert message has a space #[test(should_fail_with = "Not equal")] fn test_runtime_mismatch() { - assert_eq(dep::std::hash::pedersen([27])[0], 0, "Not equal "); -} \ No newline at end of file + assert_eq(dep::std::hash::pedersen_commitment([27])[0], 0, "Not equal "); +} diff --git a/tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/Nargo.toml b/tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/Nargo.toml index 78d98bc87a3..21bce3d2b2d 100644 --- a/tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/Nargo.toml +++ b/tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/Nargo.toml @@ -2,6 +2,4 @@ name = "should_fail_with_match" type = "bin" authors = [""] -compiler_version = "0.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/src/main.nr b/tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/src/main.nr index 8ae5e56a463..d2b7d155a32 100644 --- a/tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/src/main.nr +++ b/tooling/nargo_cli/tests/noir_test_success/should_fail_with_matches/src/main.nr @@ -10,10 +10,10 @@ fn test_should_fail_without_match() { #[test(should_fail_with = "Not equal")] fn test_should_fail_with_runtime_match() { - assert_eq(dep::std::hash::pedersen([27])[0], 0, "Not equal"); + assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0, "Not equal"); } #[test(should_fail)] fn test_should_fail_without_runtime_match() { - assert_eq(dep::std::hash::pedersen([27])[0], 0); + assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0); } diff --git a/tooling/nargo_cli/tests/rebuild.sh b/tooling/nargo_cli/tests/rebuild.sh index 9776745a1f7..d89402fb1cf 100755 --- a/tooling/nargo_cli/tests/rebuild.sh +++ b/tooling/nargo_cli/tests/rebuild.sh @@ -42,13 +42,14 @@ for dir in $base_path/*; do # Delete the JSON file after extracting bytecode field rm ./target/${dir_name}.json - # Delete the target directory in acir_artifacts if it exists + # 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 target directory to the corresponding directory in acir_artifacts - mv ./target/ $current_dir/acir_artifacts/$dir_name/ + # 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 diff --git a/tooling/nargo_cli/tests/test_libraries/bad_impl/Nargo.toml b/tooling/nargo_cli/tests/test_libraries/bad_impl/Nargo.toml index ccb03576323..62ffe95922d 100644 --- a/tooling/nargo_cli/tests/test_libraries/bad_impl/Nargo.toml +++ b/tooling/nargo_cli/tests/test_libraries/bad_impl/Nargo.toml @@ -2,6 +2,4 @@ name = "bad_impl" type = "lib" authors = [""] -compiler_version = "0.7.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/test_libraries/bad_name/Nargo.toml b/tooling/nargo_cli/tests/test_libraries/bad_name/Nargo.toml index 313e2411e83..74f6f66524d 100644 --- a/tooling/nargo_cli/tests/test_libraries/bad_name/Nargo.toml +++ b/tooling/nargo_cli/tests/test_libraries/bad_name/Nargo.toml @@ -2,6 +2,4 @@ name = "bad-name" type = "lib" authors = [""] -compiler_version = "0.7.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/test_libraries/bin_dep/Nargo.toml b/tooling/nargo_cli/tests/test_libraries/bin_dep/Nargo.toml index aa7125bf5b5..7cc99c1c5c5 100644 --- a/tooling/nargo_cli/tests/test_libraries/bin_dep/Nargo.toml +++ b/tooling/nargo_cli/tests/test_libraries/bin_dep/Nargo.toml @@ -2,6 +2,4 @@ name = "bin_dep" type = "bin" authors = [""] -compiler_version = "0.7.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/test_libraries/bin_dep/src/main.nr b/tooling/nargo_cli/tests/test_libraries/bin_dep/src/main.nr index d469d3aafcb..042c85a8afb 100644 --- a/tooling/nargo_cli/tests/test_libraries/bin_dep/src/main.nr +++ b/tooling/nargo_cli/tests/test_libraries/bin_dep/src/main.nr @@ -1,3 +1,3 @@ -fn call_dep1_then_dep2(x : Field, y : Field) { +fn call_dep1_then_dep2(x: Field, y: Field) { assert(x == y); } diff --git a/tooling/nargo_cli/tests/test_libraries/diamond_deps_1/Nargo.toml b/tooling/nargo_cli/tests/test_libraries/diamond_deps_1/Nargo.toml index 7069390334c..f7770e07469 100644 --- a/tooling/nargo_cli/tests/test_libraries/diamond_deps_1/Nargo.toml +++ b/tooling/nargo_cli/tests/test_libraries/diamond_deps_1/Nargo.toml @@ -2,7 +2,5 @@ name = "diamond_deps_1" type = "lib" authors = [""] -compiler_version = "0.7.1" - [dependencies] dep2 = { path = "../diamond_deps_2" } diff --git a/tooling/nargo_cli/tests/test_libraries/diamond_deps_1/src/lib.nr b/tooling/nargo_cli/tests/test_libraries/diamond_deps_1/src/lib.nr index d63b835c8a7..60c001ec64e 100644 --- a/tooling/nargo_cli/tests/test_libraries/diamond_deps_1/src/lib.nr +++ b/tooling/nargo_cli/tests/test_libraries/diamond_deps_1/src/lib.nr @@ -1,5 +1,5 @@ use dep::dep2::call_dep2; -pub fn call_dep1_then_dep2(x : Field, y : Field) -> Field { +pub fn call_dep1_then_dep2(x: Field, y: Field) -> Field { call_dep2(x, y) } diff --git a/tooling/nargo_cli/tests/test_libraries/diamond_deps_2/Nargo.toml b/tooling/nargo_cli/tests/test_libraries/diamond_deps_2/Nargo.toml index 4b8ece297d3..2dbba1b7a9e 100644 --- a/tooling/nargo_cli/tests/test_libraries/diamond_deps_2/Nargo.toml +++ b/tooling/nargo_cli/tests/test_libraries/diamond_deps_2/Nargo.toml @@ -2,6 +2,4 @@ name = "diamond_deps_2" type = "lib" authors = [""] -compiler_version = "0.7.1" - [dependencies] diff --git a/tooling/nargo_cli/tests/test_libraries/diamond_deps_2/src/lib.nr b/tooling/nargo_cli/tests/test_libraries/diamond_deps_2/src/lib.nr index 7ee59d2bc9d..46dce3d5600 100644 --- a/tooling/nargo_cli/tests/test_libraries/diamond_deps_2/src/lib.nr +++ b/tooling/nargo_cli/tests/test_libraries/diamond_deps_2/src/lib.nr @@ -1,6 +1,5 @@ global RESOLVE_THIS = 3; - -pub fn call_dep2(x : Field, y : Field) -> Field { +pub fn call_dep2(x: Field, y: Field) -> Field { x + y } diff --git a/tooling/nargo_fmt/build.rs b/tooling/nargo_fmt/build.rs index f2e23f9b8c1..cd93866ece9 100644 --- a/tooling/nargo_fmt/build.rs +++ b/tooling/nargo_fmt/build.rs @@ -40,6 +40,12 @@ fn generate_formatter_tests(test_file: &mut File, test_data_dir: &Path) { let input_source_path = file.path(); let input_source = std::fs::read_to_string(input_source_path).unwrap(); + let config = input_source + .lines() + .flat_map(|line| line.strip_prefix("//@")) + .collect::>() + .join("\n"); + let output_source_path = outputs_dir.join(file_name); let output_source = std::fs::read_to_string(output_source_path).unwrap(); @@ -53,9 +59,8 @@ fn format_{test_name}() {{ let (parsed_module, errors) = noirc_frontend::parse_program(&input); - assert!(errors.is_empty()); - let config = nargo_fmt::Config::default(); + let config = nargo_fmt::Config::of("{config}").unwrap(); let fmt_text = nargo_fmt::format(&input, parsed_module, &config); diff --git a/tooling/nargo_fmt/src/config.rs b/tooling/nargo_fmt/src/config.rs index dd57778da92..2bb5d97c0af 100644 --- a/tooling/nargo_fmt/src/config.rs +++ b/tooling/nargo_fmt/src/config.rs @@ -45,23 +45,29 @@ config! { max_width: usize, 100, "Maximum width of each line"; tab_spaces: usize, 4, "Number of spaces per tab"; remove_nested_parens: bool, true, "Remove nested parens"; + error_on_lost_comment: bool, true, "Error if unable to get comments"; short_array_element_width_threshold: usize, 10, "Width threshold for an array element to be considered short"; array_width: usize, 100, "Maximum width of an array literal before falling back to vertical formatting"; - single_line_if_else_max_width: usize, 100, "Maximum line length for single line if-else expressions"; + fn_call_width: usize, 60, "Maximum width of the args of a function call before falling back to vertical formatting"; + single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else expressions"; } impl Config { pub fn read(path: &Path) -> Result { - let mut config = Self::default(); let config_path = path.join("noirfmt.toml"); - let raw_toml = match std::fs::read_to_string(&config_path) { - Ok(t) => t, - Err(err) if err.kind() == std::io::ErrorKind::NotFound => String::new(), + let input = match std::fs::read_to_string(&config_path) { + Ok(input) => input, + Err(cause) if cause.kind() == std::io::ErrorKind::NotFound => String::new(), Err(cause) => return Err(ConfigError::ReadFailed(config_path, cause)), }; - let toml = toml::from_str(&raw_toml).map_err(ConfigError::MalformedFile)?; + Self::of(&input) + } + + pub fn of(s: &str) -> Result { + let mut config = Self::default(); + let toml = toml::from_str(s).map_err(ConfigError::MalformedFile)?; config.fill_from_toml(toml); Ok(config) } diff --git a/tooling/nargo_fmt/src/lib.rs b/tooling/nargo_fmt/src/lib.rs index 3e8ee570c09..d731934c3c3 100644 --- a/tooling/nargo_fmt/src/lib.rs +++ b/tooling/nargo_fmt/src/lib.rs @@ -20,6 +20,7 @@ /// in both placement and content during the formatting process. mod config; pub mod errors; +mod rewrite; mod utils; mod visitor; @@ -30,6 +31,6 @@ pub use config::Config; pub fn format(source: &str, parsed_module: ParsedModule, config: &Config) -> String { let mut fmt = FmtVisitor::new(source, config); - fmt.visit_module(parsed_module); + fmt.visit_file(parsed_module); fmt.finish() } diff --git a/tooling/nargo_fmt/src/rewrite.rs b/tooling/nargo_fmt/src/rewrite.rs new file mode 100644 index 00000000000..c1ac585985e --- /dev/null +++ b/tooling/nargo_fmt/src/rewrite.rs @@ -0,0 +1,5 @@ +mod array; +mod infix; + +pub(crate) use array::rewrite as array; +pub(crate) use infix::rewrite as infix; diff --git a/tooling/nargo_fmt/src/rewrite/array.rs b/tooling/nargo_fmt/src/rewrite/array.rs new file mode 100644 index 00000000000..9c49d827528 --- /dev/null +++ b/tooling/nargo_fmt/src/rewrite/array.rs @@ -0,0 +1,85 @@ +use noirc_frontend::{hir::resolution::errors::Span, token::Token, Expression}; + +use crate::{ + utils::{Expr, FindToken}, + visitor::FmtVisitor, +}; + +pub(crate) fn rewrite(mut visitor: FmtVisitor, array: Vec, array_span: Span) -> String { + let pattern: &[_] = &[' ', '\t']; + + visitor.indent.block_indent(visitor.config); + let nested_indent = visitor.shape(); + + let indent_str = nested_indent.indent.to_string(); + + let mut last_position = array_span.start() + 1; + let end_position = array_span.end() - 1; + + let mut items = array.into_iter().peekable(); + + let mut result = Vec::new(); + while let Some(item) = items.next() { + let item_span = item.span; + + let start: u32 = last_position; + let end = item_span.start(); + + let leading = visitor.slice(start..end).trim_matches(pattern); + let item = visitor.format_sub_expr(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 + .find_token(Token::Comma) + .map(|span| span.end() as usize) + .unwrap_or(trailing.len()); + let trailing = trailing[..offset].trim_end_matches(',').trim_matches(pattern); + last_position = item_span.end() + offset as u32; + + let (leading, _) = visitor.format_comment_in_block(leading); + let (trailing, _) = visitor.format_comment_in_block(trailing); + + result.push(Expr { leading, value: item, trailing, different_line: false }); + } + + let slice = visitor.slice(last_position..end_position); + let (comment, _) = visitor.format_comment_in_block(slice); + result.push(Expr { + leading: "".into(), + value: "".into(), + trailing: comment, + different_line: false, + }); + + visitor.indent.block_unindent(visitor.config); + + let mut items_str = String::new(); + let mut items = result.into_iter().peekable(); + while let Some(next) = items.next() { + items_str.push_str(&next.leading); + if next.leading.contains('\n') && !next.value.is_empty() { + items_str.push_str(&indent_str); + } + items_str.push_str(&next.value); + items_str.push_str(&next.trailing); + + if let Some(item) = items.peek() { + if !item.value.is_empty() { + items_str.push(','); + } + + if !item.leading.contains('\n') && !next.value.is_empty() { + items_str.push(' '); + } + } + } + + crate::visitor::expr::wrap_exprs( + "[", + "]", + items_str.trim().into(), + nested_indent, + visitor.shape(), + true, + ) +} diff --git a/tooling/nargo_fmt/src/rewrite/infix.rs b/tooling/nargo_fmt/src/rewrite/infix.rs new file mode 100644 index 00000000000..0fbfa07a841 --- /dev/null +++ b/tooling/nargo_fmt/src/rewrite/infix.rs @@ -0,0 +1,112 @@ +use std::iter::zip; + +use noirc_frontend::{Expression, ExpressionKind}; + +use crate::{ + utils::{first_line_width, is_single_line}, + visitor::{ExpressionType, FmtVisitor, Shape}, +}; + +pub(crate) fn rewrite(visitor: FmtVisitor, expr: Expression, shape: Shape) -> String { + match flatten(visitor.fork(), &expr) { + Some((exprs, separators)) => rewrite_single_line(shape, &exprs, &separators) + .unwrap_or_else(|| rewrite_multiline(visitor, &exprs, &separators)), + None => { + let ExpressionKind::Infix(infix) = expr.kind else { unreachable!() }; + + format!( + "{} {} {}", + visitor.format_sub_expr(infix.lhs), + infix.operator.contents.as_string(), + visitor.format_sub_expr(infix.rhs) + ) + } + } +} + +fn rewrite_single_line(shape: Shape, exprs: &[String], separators: &[String]) -> Option { + let mut result = String::new(); + + for (rewrite, separator) in zip(exprs, separators) { + if !is_single_line(rewrite) || result.len() > shape.width { + return None; + } + + result.push_str(rewrite); + result.push(' '); + result.push_str(separator); + result.push(' '); + } + + let last = exprs.last().unwrap(); + result.push_str(last); + + if first_line_width(&result) > shape.width { + return None; + } + + result.into() +} + +fn rewrite_multiline(visitor: FmtVisitor, exprs: &[String], separators: &[String]) -> String { + let mut visitor = visitor.fork(); + visitor.indent.block_indent(visitor.config); + let indent_str = visitor.indent.to_string_with_newline(); + + let mut result = exprs[0].clone(); + + for (rewrite, separator) in exprs[1..].iter().zip(separators.iter()) { + result.push_str(&indent_str); + result.push_str(separator); + result.push(' '); + result.push_str(rewrite); + } + + result +} + +pub(crate) fn flatten( + mut visitor: FmtVisitor, + mut node: &Expression, +) -> Option<(Vec, Vec)> { + let top_operator = match node.kind { + ExpressionKind::Infix(ref infix) => infix.operator.contents, + _ => return None, + }; + + let mut result = Vec::new(); + + let mut stack: Vec<&Expression> = Vec::new(); + let mut separators = Vec::new(); + + loop { + match &node.kind { + ExpressionKind::Infix(infix) if top_operator == infix.operator.contents => { + stack.push(node); + node = &infix.lhs; + } + _ => { + let rewrite = if result.is_empty() { + visitor.format_expr(node.clone(), ExpressionType::SubExpression) + } else { + visitor.indent.block_indent(visitor.config); + visitor.format_expr(node.clone(), ExpressionType::SubExpression) + }; + + result.push(rewrite); + + let Some(pop) = stack.pop() else { break; }; + + match &pop.kind { + ExpressionKind::Infix(infix) => { + separators.push(infix.operator.contents.to_string()); + node = &infix.rhs; + } + _ => unreachable!(), + } + } + } + } + + (result, separators).into() +} diff --git a/tooling/nargo_fmt/src/utils.rs b/tooling/nargo_fmt/src/utils.rs index 5b2cf2f3c47..13938079e68 100644 --- a/tooling/nargo_fmt/src/utils.rs +++ b/tooling/nargo_fmt/src/utils.rs @@ -2,15 +2,7 @@ use crate::visitor::FmtVisitor; use noirc_frontend::hir::resolution::errors::Span; use noirc_frontend::lexer::Lexer; use noirc_frontend::token::Token; -use noirc_frontend::{Expression, Ident}; - -pub(crate) fn recover_comment_removed(original: &str, new: String) -> String { - if changed_comment_content(original, &new) { - original.to_string() - } else { - new - } -} +use noirc_frontend::{Expression, Ident, Param, Visibility}; pub(crate) fn changed_comment_content(original: &str, new: &str) -> bool { comments(original).ne(comments(new)) @@ -119,22 +111,19 @@ impl<'me, T> Exprs<'me, T> { } pub(crate) trait FindToken { - fn find_token(&self, token: Token) -> Option; + fn find_token(&self, token: Token) -> Option; fn find_token_with(&self, f: impl Fn(&Token) -> bool) -> Option; } impl FindToken for str { - fn find_token(&self, token: Token) -> Option { - Lexer::new(self) - .flatten() - .find_map(|it| (it.token() == &token).then(|| it.to_span().start())) + fn find_token(&self, token: Token) -> Option { + 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 { Lexer::new(self) .skip_comments(false) .flatten() - .into_iter() .find_map(|spanned| f(spanned.token()).then(|| spanned.to_span().end())) } } @@ -163,7 +152,9 @@ pub(crate) fn find_comment_end(slice: &str, is_last: bool) -> usize { } let newline_index = slice.find('\n'); - if let Some(separator_index) = slice.find_token(Token::Comma).map(|index| index as usize) { + if let Some(separator_index) = + slice.find_token(Token::Comma).map(|index| index.start() as usize) + { match (block_open_index, newline_index) { (Some(block), None) if block > separator_index => separator_index + 1, (Some(block), None) => { @@ -198,6 +189,10 @@ fn comment_len(comment: &str) -> usize { } } +pub(crate) fn count_newlines(slice: &str) -> usize { + bytecount::count(slice.as_bytes(), b'\n') +} + pub(crate) trait Item { fn span(&self) -> Span; @@ -241,3 +236,42 @@ impl Item for (Ident, Expression) { } } } + +impl Item for Param { + fn span(&self) -> Span { + self.span + } + + fn format(self, visitor: &FmtVisitor) -> String { + let visibility = match self.visibility { + Visibility::Public => "pub ", + Visibility::Private => "", + }; + let pattern = visitor.slice(self.pattern.span()); + let ty = visitor.slice(self.typ.span.unwrap()); + + format!("{pattern}: {visibility}{ty}") + } +} + +impl Item for Ident { + fn span(&self) -> Span { + self.span() + } + + fn format(self, visitor: &FmtVisitor) -> String { + visitor.slice(self.span()).into() + } +} + +pub(crate) fn first_line_width(exprs: &str) -> usize { + exprs.lines().next().map_or(0, |line: &str| line.chars().count()) +} + +pub(crate) fn is_single_line(s: &str) -> bool { + !s.chars().any(|c| c == '\n') +} + +pub(crate) fn last_line_contains_single_line_comment(s: &str) -> bool { + s.lines().last().map_or(false, |line| line.contains("//")) +} diff --git a/tooling/nargo_fmt/src/visitor.rs b/tooling/nargo_fmt/src/visitor.rs index bc769e3f298..cf3b3a41e8a 100644 --- a/tooling/nargo_fmt/src/visitor.rs +++ b/tooling/nargo_fmt/src/visitor.rs @@ -1,8 +1,8 @@ -mod expr; +pub(crate) mod expr; mod item; mod stmt; -use noirc_frontend::{hir::resolution::errors::Span, token::Token}; +use noirc_frontend::{hir::resolution::errors::Span, lexer::Lexer, token::Token}; use crate::{ config::Config, @@ -10,16 +10,18 @@ use crate::{ }; pub(crate) struct FmtVisitor<'me> { - config: &'me Config, + ignore_next_node: bool, + pub(crate) config: &'me Config, buffer: String, pub(crate) source: &'me str, - indent: Indent, + pub(crate) indent: Indent, last_position: u32, } impl<'me> FmtVisitor<'me> { pub(crate) fn new(source: &'me str, config: &'me Config) -> Self { Self { + ignore_next_node: false, buffer: String::new(), config, source, @@ -33,16 +35,25 @@ impl<'me> FmtVisitor<'me> { &self.source[span.start() as usize..span.end() as usize] } + fn span_after(&self, span: impl Into, token: Token) -> Span { + let span = span.into(); + + let slice = self.slice(span); + let offset = slice.find_token(token).unwrap().end(); + + (span.start() + offset..span.end()).into() + } + fn span_before(&self, span: impl Into, token: Token) -> Span { let span = span.into(); let slice = self.slice(span); - let offset = slice.find_token(token).unwrap(); + let offset = slice.find_token(token).unwrap().start(); (span.start() + offset..span.end()).into() } - fn shape(&self) -> Shape { + pub(crate) fn shape(&self) -> Shape { Shape { width: self.config.max_width.saturating_sub(self.indent.width()), indent: self.indent, @@ -52,6 +63,7 @@ impl<'me> FmtVisitor<'me> { pub(crate) fn fork(&self) -> Self { Self { buffer: String::new(), + ignore_next_node: self.ignore_next_node, config: self.config, source: self.source, last_position: self.last_position, @@ -63,30 +75,54 @@ impl<'me> FmtVisitor<'me> { self.buffer } - fn with_indent(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { - self.indent.block_indent(self.config); - let ret = f(self); - self.indent.block_unindent(self.config); - ret - } - fn at_start(&self) -> bool { self.buffer.is_empty() } fn push_str(&mut self, s: &str) { + let comments = Lexer::new(s).skip_comments(false).flatten().flat_map(|token| { + if let Token::LineComment(content, _) | Token::BlockComment(content, _) = + token.into_token() + { + let content = content.trim(); + content.strip_prefix("noir-fmt:").map(ToOwned::to_owned) + } else { + None + } + }); + + for comment in comments { + match comment.as_str() { + "ignore" => self.ignore_next_node = true, + this => unreachable!("unknown settings {this}"), + } + } + self.buffer.push_str(s); } #[track_caller] fn push_rewrite(&mut self, rewrite: String, span: Span) { - let rewrite = utils::recover_comment_removed(self.slice(span), rewrite); + let original = self.slice(span); + let changed_comment_content = utils::changed_comment_content(original, &rewrite); + + if changed_comment_content && self.config.error_on_lost_comment { + panic!("not formatted because a comment would be lost: {rewrite:?}"); + } + self.format_missing_indent(span.start(), true); + + let rewrite = if changed_comment_content || std::mem::take(&mut self.ignore_next_node) { + original.to_string() + } else { + rewrite + }; + self.push_str(&rewrite); - } - fn format_missing(&mut self, end: u32) { - self.format_missing_inner(end, |this, slice, _| this.push_str(slice)); + if rewrite.starts_with('{') && rewrite.ends_with('}') { + self.ignore_next_node = false; + } } #[track_caller] @@ -94,7 +130,7 @@ impl<'me> FmtVisitor<'me> { self.format_missing_inner(end, |this, last_slice, slice| { this.push_str(last_slice.trim_end()); - if last_slice == slice && !this.at_start() { + if (last_slice == slice && !this.at_start()) || this.buffer.ends_with("*/") { this.push_str("\n"); } @@ -127,15 +163,54 @@ impl<'me> FmtVisitor<'me> { self.push_vertical_spaces(slice); process_last_slice(self, "", slice); } else { - process_last_slice(self, slice, slice); + let (result, last_end) = self.format_comment_in_block(slice); + if result.trim().is_empty() { + process_last_slice(self, slice, slice); + } else { + let last_snippet = &slice[last_end as usize..]; + self.push_str(&result); + process_last_slice(self, last_snippet, &result); + } } } + pub(crate) fn format_comment_in_block(&mut self, slice: &str) -> (String, u32) { + let mut result = String::new(); + let comments = Lexer::new(slice).skip_comments(false).skip_whitespaces(false).flatten(); + + let indent = self.indent.to_string(); + for comment in comments { + let span = comment.to_span(); + + match comment.token() { + Token::LineComment(_, _) | Token::BlockComment(_, _) => { + let comment = &slice[span.start() as usize..span.end() as usize]; + if result.ends_with('\n') { + result.push_str(&indent); + } else if !self.at_start() { + result.push(' '); + } + result.push_str(comment); + } + Token::Whitespace(whitespaces) => { + let mut visitor = self.fork(); + if whitespaces.contains('\n') { + visitor.push_vertical_spaces(whitespaces.trim_matches(' ')); + result.push_str(&visitor.finish()); + } + } + _ => {} + } + } + + (result, slice.len() as u32) + } + fn push_vertical_spaces(&mut self, slice: &str) { let newline_upper_bound = 2; let newline_lower_bound = 1; - let mut newline_count = bytecount::count(slice.as_bytes(), b'\n'); + let mut newline_count = utils::count_newlines(slice); let offset = self.buffer.chars().rev().take_while(|c| *c == '\n').count(); if newline_count + offset > newline_upper_bound { @@ -169,37 +244,37 @@ impl<'me> FmtVisitor<'me> { } #[derive(Clone, Copy, Debug, Default)] -struct Indent { +pub(crate) struct Indent { block_indent: usize, } impl Indent { - fn width(&self) -> usize { + pub(crate) fn width(&self) -> usize { self.block_indent } - fn block_indent(&mut self, config: &Config) { + pub(crate) fn block_indent(&mut self, config: &Config) { self.block_indent += config.tab_spaces; } - fn block_unindent(&mut self, config: &Config) { + pub(crate) fn block_unindent(&mut self, config: &Config) { self.block_indent -= config.tab_spaces; } - fn to_string_with_newline(self) -> String { + pub(crate) fn to_string_with_newline(self) -> String { "\n".to_string() + &self.to_string() } #[allow(clippy::inherent_to_string)] - fn to_string(self) -> String { + pub(crate) fn to_string(self) -> String { " ".repeat(self.block_indent) } } #[derive(Clone, Copy, Debug)] -struct Shape { - width: usize, - indent: Indent, +pub(crate) struct Shape { + pub(crate) width: usize, + pub(crate) indent: Indent, } #[derive(PartialEq, Eq, Debug)] diff --git a/tooling/nargo_fmt/src/visitor/expr.rs b/tooling/nargo_fmt/src/visitor/expr.rs index 8f855cd6157..8492fd5c05d 100644 --- a/tooling/nargo_fmt/src/visitor/expr.rs +++ b/tooling/nargo_fmt/src/visitor/expr.rs @@ -1,22 +1,21 @@ use noirc_frontend::{ - hir::resolution::errors::Span, token::Token, ArrayLiteral, BlockExpression, + hir::resolution::errors::Span, lexer::Lexer, token::Token, ArrayLiteral, BlockExpression, ConstructorExpression, Expression, ExpressionKind, IfExpression, Literal, Statement, StatementKind, UnaryOp, }; use super::{ExpressionType, FmtVisitor, Indent, Shape}; use crate::{ - utils::{self, Expr, FindToken, Item}, + rewrite, + utils::{self, first_line_width, Expr, FindToken, Item}, Config, }; 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); self.push_rewrite(rewrite, span); - self.last_position = span.end(); } @@ -32,7 +31,7 @@ impl FmtVisitor<'_> { match kind { ExpressionKind::Block(block) => { let mut visitor = self.fork(); - visitor.visit_block(block, span, true); + visitor.visit_block(block, span); visitor.buffer } ExpressionKind::Prefix(prefix) => { @@ -54,20 +53,22 @@ impl FmtVisitor<'_> { ExpressionKind::Cast(cast) => { format!("{} as {}", self.format_sub_expr(cast.lhs), cast.r#type) } - ExpressionKind::Infix(infix) => { - format!( - "{} {} {}", - self.format_sub_expr(infix.lhs), - infix.operator.contents.as_string(), - self.format_sub_expr(infix.rhs) - ) + 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.fork(), false, call_expr.arguments, args_span); + let args = format_parens( + self.config.fn_call_width.into(), + self.fork(), + false, + call_expr.arguments, + args_span, + ); format!("{callee}{args}") } @@ -79,7 +80,13 @@ impl FmtVisitor<'_> { let object = self.format_sub_expr(method_call_expr.object); let method = method_call_expr.method_name.to_string(); - let args = format_parens(self.fork(), false, method_call_expr.arguments, args_span); + let args = format_parens( + self.config.fn_call_width.into(), + self.fork(), + false, + method_call_expr.arguments, + args_span, + ); format!("{object}.{method}{args}") } @@ -97,7 +104,7 @@ impl FmtVisitor<'_> { format!("{collection}{index}") } ExpressionKind::Tuple(exprs) => { - format_parens(self.fork(), exprs.len() == 1, exprs, span) + format_parens(None, self.fork(), exprs.len() == 1, exprs, span) } ExpressionKind::Literal(literal) => match literal { Literal::Integer(_) | Literal::Bool(_) | Literal::Str(_) | Literal::FmtStr(_) => { @@ -110,7 +117,7 @@ impl FmtVisitor<'_> { format!("[{repeated}; {length}]") } Literal::Array(ArrayLiteral::Standard(exprs)) => { - format_brackets(self.fork(), false, exprs, span) + rewrite::array(self.fork(), exprs, span) } Literal::Unit => "()".to_string(), }, @@ -192,7 +199,7 @@ impl FmtVisitor<'_> { self.format_if(*if_expr) } - ExpressionKind::Variable(_) | ExpressionKind::Lambda(_) => self.slice(span).to_string(), + ExpressionKind::Lambda(_) | ExpressionKind::Variable(_) => self.slice(span).to_string(), ExpressionKind::Error => unreachable!(), } } @@ -281,14 +288,9 @@ impl FmtVisitor<'_> { format!("{type_name} {{{fields}}}") } - pub(crate) fn visit_block( - &mut self, - block: BlockExpression, - block_span: Span, - should_indent: bool, - ) { + pub(crate) fn visit_block(&mut self, block: BlockExpression, block_span: Span) { if block.is_empty() { - self.visit_empty_block(block_span, should_indent); + self.visit_empty_block(block_span); return; } @@ -297,20 +299,13 @@ impl FmtVisitor<'_> { self.trim_spaces_after_opening_brace(&block.0); - self.with_indent(|this| { - this.visit_stmts(block.0); - }); + self.indent.block_indent(self.config); - let slice = self.slice(self.last_position..block_span.end() - 1).trim_end(); - self.push_str(slice); + self.visit_stmts(block.0); + let span = (self.last_position..block_span.end() - 1).into(); + self.close_block(span); self.last_position = block_span.end(); - - self.push_str("\n"); - if should_indent { - self.push_str(&self.indent.to_string()); - } - self.push_str("}"); } fn trim_spaces_after_opening_brace(&mut self, block: &[Statement]) { @@ -322,26 +317,56 @@ impl FmtVisitor<'_> { } } - fn visit_empty_block(&mut self, block_span: Span, should_indent: bool) { + pub(crate) fn visit_empty_block(&mut self, block_span: Span) { let slice = self.slice(block_span); let comment_str = slice[1..slice.len() - 1].trim(); - let block_str = if comment_str.is_empty() { - "{}".to_string() + + if comment_str.is_empty() { + self.push_str("{}"); } else { + self.push_str("{"); self.indent.block_indent(self.config); - let open_indent = self.indent.to_string(); - self.indent.block_unindent(self.config); - let close_indent = if should_indent { self.indent.to_string() } else { String::new() }; - - let ret = format!("{{\n{open_indent}{comment_str}\n{close_indent}}}"); - ret + self.close_block(block_span); }; + self.last_position = block_span.end(); - self.push_str(&block_str); + } + + pub(crate) fn close_block(&mut self, span: Span) { + let slice = self.slice(span); + + for spanned in Lexer::new(slice).skip_comments(false).flatten() { + match spanned.token() { + Token::LineComment(_, _) | Token::BlockComment(_, _) => { + let token_span = spanned.to_span(); + + let offset = token_span.start(); + let sub_slice = &slice[token_span.start() as usize..token_span.end() as usize]; + + let span_in_between = span.start()..span.start() + offset; + let slice_in_between = self.slice(span_in_between); + let comment_on_same_line = !slice_in_between.contains('\n'); + + if comment_on_same_line { + self.push_str(" "); + self.push_str(sub_slice); + } else { + self.push_str(&self.indent.to_string_with_newline()); + self.push_str(sub_slice); + } + } + _ => {} + } + } + + self.indent.block_unindent(self.config); + self.push_str(&self.indent.to_string_with_newline()); + self.push_str("}"); } } -fn format_expr_seq( +#[allow(clippy::too_many_arguments)] +pub(crate) fn format_seq( prefix: &str, suffix: &str, mut visitor: FmtVisitor, @@ -349,6 +374,7 @@ fn format_expr_seq( exprs: Vec, span: Span, tactic: Tactic, + soft_newline: bool, ) -> String { visitor.indent.block_indent(visitor.config); @@ -358,7 +384,7 @@ fn format_expr_seq( visitor.indent.block_unindent(visitor.config); - wrap_exprs(prefix, suffix, exprs, nested_indent, visitor.shape()) + wrap_exprs(prefix, suffix, exprs, nested_indent, visitor.shape(), soft_newline) } fn format_brackets( @@ -368,7 +394,7 @@ fn format_brackets( span: Span, ) -> String { let array_width = visitor.config.array_width; - format_expr_seq( + format_seq( "[", "]", visitor, @@ -376,16 +402,19 @@ fn format_brackets( exprs, span, Tactic::LimitedHorizontalVertical(array_width), + false, ) } fn format_parens( + max_width: Option, visitor: FmtVisitor, trailing_comma: bool, exprs: Vec, span: Span, ) -> String { - format_expr_seq("(", ")", visitor, trailing_comma, exprs, span, Tactic::Horizontal) + let tactic = max_width.map(Tactic::LimitedHorizontalVertical).unwrap_or(Tactic::Horizontal); + format_seq("(", ")", visitor, trailing_comma, exprs, span, tactic, false) } fn format_exprs( @@ -471,16 +500,20 @@ fn format_exprs( result } -fn wrap_exprs( +pub(crate) fn wrap_exprs( prefix: &str, suffix: &str, exprs: String, nested_shape: Shape, shape: Shape, + soft_newline: bool, ) -> String { - let first_line_width = exprs.lines().next().map_or(0, |line| line.chars().count()); + let first_line_width = first_line_width(&exprs); + + let force_one_line = + if soft_newline { !exprs.contains('\n') } else { first_line_width <= shape.width }; - if first_line_width <= shape.width { + if force_one_line { let allow_trailing_newline = exprs .lines() .last() @@ -503,8 +536,8 @@ fn wrap_exprs( } } -#[derive(PartialEq, Eq)] -enum Tactic { +#[derive(PartialEq, Eq, Clone, Copy)] +pub(crate) enum Tactic { Horizontal, HorizontalVertical, LimitedHorizontalVertical(usize), diff --git a/tooling/nargo_fmt/src/visitor/item.rs b/tooling/nargo_fmt/src/visitor/item.rs index 09031082fa3..7774618afea 100644 --- a/tooling/nargo_fmt/src/visitor/item.rs +++ b/tooling/nargo_fmt/src/visitor/item.rs @@ -1,33 +1,149 @@ use noirc_frontend::{ parser::{Item, ItemKind}, - NoirFunction, ParsedModule, + token::Token, + Distinctness, NoirFunction, ParsedModule, Visibility, }; +use crate::{utils::last_line_contains_single_line_comment, visitor::expr::format_seq}; + +use super::expr::Tactic::LimitedHorizontalVertical; + impl super::FmtVisitor<'_> { fn format_fn_before_block(&self, func: NoirFunction, start: u32) -> (String, bool) { - let slice = self.slice(start..func.span().start()); - let force_brace_newline = slice.contains("//"); - (slice.trim_end().to_string(), force_brace_newline) + let tactic = LimitedHorizontalVertical(self.config.max_width); + + let name_span = func.name_ident().span(); + let func_span = func.span(); + + let mut result = self.slice(start..name_span.end()).to_owned(); + + let params_open = + self.span_before(name_span.end()..func_span.start(), Token::LeftParen).start(); + + let last_span = if func.parameters().is_empty() { + params_open..func_span.start() + } else { + func.parameters().last().unwrap().span.end()..func_span.start() + }; + + let params_end = self.span_after(last_span, Token::RightParen).start(); + + let params_span = params_open..params_end; + let return_type_span = func.return_type().span; + let parameters = func.def.parameters; + + if !func.def.generics.is_empty() { + let full_span = name_span.end()..params_open; + let start = name_span.end(); + let end = self.span_after(full_span, Token::Greater).start(); + + let generics = func.def.generics; + let span = (start..end).into(); + let generics = format_seq("<", ">", self.fork(), false, generics, span, tactic, false); + + result.push_str(&generics); + } + + let parameters = if parameters.is_empty() { + self.slice(params_span).into() + } else { + format_seq("(", ")", self.fork(), false, parameters, params_span.into(), tactic, true) + }; + + result.push_str(¶meters); + + if let Some(span) = return_type_span { + result.push_str(" -> "); + + if let Distinctness::Distinct = func.def.return_distinctness { + result.push_str("distinct "); + } + + if let Visibility::Public = func.def.return_visibility { + result.push_str("pub "); + } + + result.push_str(self.slice(span)); + + let slice = self.slice(span.end()..func_span.start()); + if !slice.trim().is_empty() { + result.push_str(slice); + } + } else { + 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)) + } + + pub(crate) fn visit_file(&mut self, module: ParsedModule) { + self.visit_module(module); + self.format_missing_indent(self.source.len() as u32, false); } - pub(crate) fn visit_module(&mut self, module: ParsedModule) { + fn visit_module(&mut self, module: ParsedModule) { for Item { kind, span } in module.items { match kind { ItemKind::Function(func) => { + self.format_missing_indent(span.start(), true); + + if std::mem::take(&mut self.ignore_next_node) { + self.push_str(self.slice(span)); + self.last_position = span.end(); + continue; + } + let (fn_before_block, force_brace_newline) = self.format_fn_before_block(func.clone(), span.start()); - self.format_missing_indent(span.start(), false); - self.push_str(&fn_before_block); self.push_str(if force_brace_newline { "\n" } else { " " }); - self.visit_block(func.def.body, func.def.span, false); + self.visit_block(func.def.body, func.def.span); + } + ItemKind::Submodules(module) => { + self.format_missing_indent(span.start(), true); + + if std::mem::take(&mut self.ignore_next_node) { + self.push_str(self.slice(span)); + self.last_position = span.end(); + continue; + } + + let name = module.name; + let after_brace = self.span_after(span, Token::LeftBrace).start(); + self.last_position = after_brace; + + let keyword = if module.is_contract { "contract" } else { "mod" }; + + self.push_str(&format!("{keyword} {name} ")); + + if module.contents.items.is_empty() { + self.visit_empty_block((after_brace - 1..span.end()).into()); + continue; + } else { + self.push_str("{"); + self.indent.block_indent(self.config); + self.visit_module(module.contents); + } + + self.close_block((self.last_position..span.end() - 1).into()); + self.last_position = span.end(); + } + ItemKind::Import(_) + | ItemKind::Struct(_) + | ItemKind::Trait(_) + | ItemKind::TraitImpl(_) + | ItemKind::Impl(_) + | ItemKind::TypeAlias(_) + | ItemKind::Global(_) + | ItemKind::ModuleDecl(_) => { + self.push_rewrite(self.slice(span).to_string(), span); + self.last_position = span.end(); } - _ => self.format_missing(span.end()), } } - - self.format_missing_indent(self.source.len() as u32, false); } } diff --git a/tooling/nargo_fmt/src/visitor/stmt.rs b/tooling/nargo_fmt/src/visitor/stmt.rs index 0a814ebd136..b6dd67323fa 100644 --- a/tooling/nargo_fmt/src/visitor/stmt.rs +++ b/tooling/nargo_fmt/src/visitor/stmt.rs @@ -1,6 +1,8 @@ use std::iter::zip; -use noirc_frontend::{ConstrainKind, ConstrainStatement, ExpressionKind, Statement, StatementKind}; +use noirc_frontend::{ + ConstrainKind, ConstrainStatement, ExpressionKind, ForRange, Statement, StatementKind, +}; use super::ExpressionType; @@ -55,7 +57,24 @@ impl super::FmtVisitor<'_> { self.push_rewrite(constrain, span); } - StatementKind::Assign(_) | StatementKind::For(_) => self.format_missing(span.end()), + StatementKind::For(for_stmt) => { + let identifier = self.slice(for_stmt.identifier.span()); + let range = match for_stmt.range { + ForRange::Range(start, end) => format!( + "{}..{}", + self.format_sub_expr(start), + self.format_sub_expr(end) + ), + ForRange::Array(array) => self.format_sub_expr(array), + }; + let block = self.format_sub_expr(for_stmt.block); + + let result = format!("for {identifier} in {range} {block}"); + self.push_rewrite(result, span); + } + StatementKind::Assign(_) => { + self.push_rewrite(self.slice(span).to_string(), span); + } StatementKind::Error => unreachable!(), } diff --git a/tooling/nargo_fmt/tests/expected/array.nr b/tooling/nargo_fmt/tests/expected/array.nr index fdf81d3595c..3341afb31a5 100644 --- a/tooling/nargo_fmt/tests/expected/array.nr +++ b/tooling/nargo_fmt/tests/expected/array.nr @@ -1,42 +1,38 @@ fn big_array() { - [1, - 10, - 100, - 1000, - 10000, - 100000, - 1000000, - 10000000, - 100000000, - 1000000000, - 10000000000, - 100000000000, - 1000000000000, - 10000000000000, - 100000000000000, - 1000000000000000, - 10000000000000000, - 100000000000000000, - 1000000000000000000, + [ + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, 1000000000000000, 10000000000000000, 100000000000000000, 1000000000000000000, 10000000000000000000, 100000000000000000000, 1000000000000000000000, 10000000000000000000000, 100000000000000000000000, - 1000000000000000000000000]; + 1000000000000000000000000 + ]; - [1, 10]; + [ + 1, + 10 + ]; - [// hello! - 1, 10]; + [ + // hello! + 1, + 10 + ]; - [// hello! - 1, // asd - 10]; + [ + // hello! + 1, + // asd + 10 + ]; - [// hello! - 1, // asd - 10// asdasd + [ + // hello! + 1, + // asd + 10 + // asdasd ]; [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]], [[13, 14, 15], [16, 17, 18]]]; diff --git a/tooling/nargo_fmt/tests/expected/call.nr b/tooling/nargo_fmt/tests/expected/call.nr index 8f627ed1223..3c9b36e8403 100644 --- a/tooling/nargo_fmt/tests/expected/call.nr +++ b/tooling/nargo_fmt/tests/expected/call.nr @@ -15,9 +15,11 @@ fn foo() { Comment */ 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); @@ -28,4 +30,7 @@ fn foo() { assert(x, "message"); assert(x == y); + + assert(p4_affine.eq(Gaffine::new(6890855772600357754907169075114257697580319025794532037257385534741338397365, + 4338620300185947561074059802482547481416142213883829469920100239455078257889))); } diff --git a/tooling/nargo_fmt/tests/expected/comment.nr b/tooling/nargo_fmt/tests/expected/comment.nr index b6ac52a236a..fae425acfd0 100644 --- a/tooling/nargo_fmt/tests/expected/comment.nr +++ b/tooling/nargo_fmt/tests/expected/comment.nr @@ -3,8 +3,8 @@ fn comment1() { } // random comment -fn comment2() { - // Test + +fn comment2() { // Test } fn comment3() // some comment diff --git a/tooling/nargo_fmt/tests/expected/contract.nr b/tooling/nargo_fmt/tests/expected/contract.nr new file mode 100644 index 00000000000..0d9bd2f100d --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/contract.nr @@ -0,0 +1,78 @@ +// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +// Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +// Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. +// Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +contract Benchmarking { + use dep::value_note::{ + utils::{increment, decrement}, + value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}, + }; + + use dep::aztec::{ + context::{Context}, + note::{utils as note_utils, note_getter_options::NoteGetterOptions, note_header::NoteHeader}, + selector::compute_selector, + log::emit_unencrypted_log, + state_vars::{map::Map, public_state::PublicState, set::Set}, + types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, + types::address::{AztecAddress}, + }; + + struct Storage { + notes: Map>, + balances: Map>, + } + + impl Storage { + fn init(context: Context) -> pub Self { + Storage { + notes: Map::new(context, 1, |context, slot| { Set::new(context, slot, ValueNoteMethods) }), + balances: Map::new(context, 2, |context, slot| { PublicState::new(context, slot, FieldSerializationMethods) }), + } + } + } + + #[aztec(private)] + fn constructor() {} + + // Nec tincidunt praesent semper feugiat nibh sed pulvinar. Nibh nisl condimentum id venenatis a. + #[aztec(private)] + fn create_note(owner: Field, value: Field) { + increment(storage.notes.at(owner), value, owner); + } + + // Diam quam nulla porttitor massa id. Elit ullamcorper dignissim cras tincidunt lobortis feugiat. + #[aztec(private)] + fn recreate_note(owner: Field, index: u32) { + let owner_notes = storage.notes.at(owner); + let getter_options = NoteGetterOptions::new().set_limit(1).set_offset(index); + let notes = owner_notes.get_notes(getter_options); + let note = notes[0].unwrap_unchecked(); + owner_notes.remove(note); + increment(owner_notes, note.value, owner); + } + + // Ultrices in iaculis nunc sed augue lacus. + #[aztec(public)] + 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(), + compute_selector("broadcast(Field)"), + [owner]); + } + + // Est ultricies integer quis auctor elit sed. In nibh mauris cursus mattis molestie a iaculis. + #[aztec(public)] + fn broadcast(owner: Field) { + 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] { + let note_header = NoteHeader::new(contract_address, nonce, storage_slot); + note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, preimage) + } +} + +// Uses the token bridge contract, which tells which input token we need to talk to and handles the exit funds to L1 +contract Uniswap {} diff --git a/tooling/nargo_fmt/tests/expected/expr.nr b/tooling/nargo_fmt/tests/expected/expr.nr index 20eb6ad547d..03a26835ee3 100644 --- a/tooling/nargo_fmt/tests/expected/expr.nr +++ b/tooling/nargo_fmt/tests/expected/expr.nr @@ -2,8 +2,7 @@ fn qux() { {} - { - /* a block with a comment */ + { /* a block with a comment */ } {} { @@ -50,7 +49,7 @@ fn only_comment() { fn only_comments() { // Keep this here -// Keep this here + // Keep this here } fn only_comments() { @@ -72,6 +71,22 @@ fn test() { 34 } +fn line() { + 42; // 42 +} + +fn line() { + 42; // 42 + 42; + // hello +} + +fn line() { + 42; // 42 + // 42 + // hello +} + fn parenthesized() { value + (x as Field) } @@ -86,9 +101,9 @@ fn parenthesized() { fn parenthesized() { value + ( - // line - x as Field - ) + // line + x as Field + ) } fn constructor() { diff --git a/tooling/nargo_fmt/tests/expected/fn.nr b/tooling/nargo_fmt/tests/expected/fn.nr index 89484dc83c2..5bca2dd8bb1 100644 --- a/tooling/nargo_fmt/tests/expected/fn.nr +++ b/tooling/nargo_fmt/tests/expected/fn.nr @@ -1 +1,33 @@ fn main(x: pub u8, y: u8) {} + +fn main(x: pub u8, y: u8) -> pub Field {} + +fn main(x: A, y: B) -> pub Field where A: Eq, B: Eq {} + +fn main() +// hello +{} + +fn main( + // hello +) {} + +fn main( + // hello + unit: () +) {} + +fn main() where T: Eq {} + +fn main( + tape: [Field; TAPE_LEN], + initial_registers: [Field; REGISTER_COUNT], + initial_memory: [Field; MEM_COUNT], + initial_program_counter: Field, + initial_call_stack: [Field; MAX_CALL_STACK], + 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 main() -> distinct pub [Field;2] {} diff --git a/tooling/nargo_fmt/tests/expected/for.nr b/tooling/nargo_fmt/tests/expected/for.nr new file mode 100644 index 00000000000..98dff672bef --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/for.nr @@ -0,0 +1,21 @@ +fn for_stmt() { + for elem in self { + ret &= predicate(elem); + } +} + +fn for_stmt() { + for i in 0..(C1 - 1) { + for _j in 1..(C1 - i - 1) { + b *= b; + } + + z *= if b == 1 { 1 } else { c }; + + c *= c; + + t *= if b == 1 { 1 } else { c }; + + b = t; + } +} diff --git a/tooling/nargo_fmt/tests/expected/global.nr b/tooling/nargo_fmt/tests/expected/global.nr new file mode 100644 index 00000000000..e73cf96ccbe --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/global.nr @@ -0,0 +1,9 @@ +//! Super module :] + +// super global variable +global answer = 42; + +// Super module :] + +// super global variable +global answer = 42; diff --git a/tooling/nargo_fmt/tests/expected/if.nr b/tooling/nargo_fmt/tests/expected/if.nr index 9893239750c..39ad7d18cdd 100644 --- a/tooling/nargo_fmt/tests/expected/if.nr +++ b/tooling/nargo_fmt/tests/expected/if.nr @@ -1,4 +1,17 @@ +//@error_on_lost_comment=false fn main() { + let (x,y) = if is_square(gx1) { + (x1, sqrt(gx1)) + } else { + (x2, sqrt(gx2)) + }; + + let n = if x != y { + if x != 20 { slice.push_back(y) } else { slice } + } else { + slice + }; + if false { (); (); diff --git a/tooling/nargo_fmt/tests/expected/ignore.nr b/tooling/nargo_fmt/tests/expected/ignore.nr new file mode 100644 index 00000000000..1c84e178f34 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/ignore.nr @@ -0,0 +1,26 @@ +fn main() { + // noir-fmt:ignore + assert( x != y ); + assert(x != y); + { + // noir-fmt:ignore + }; + assert(x != y); +} +// noir-fmt:ignore +fn main() { +1; +2; +3; +} +// noir-fmt:ignore +mod items { +fn hello() {} +} + +fn mk_array() { + // noir-fmt:ignore + let array = [1, + ]; + let array = [1]; +} diff --git a/tooling/nargo_fmt/tests/expected/infix.nr b/tooling/nargo_fmt/tests/expected/infix.nr index f930f79ebcb..cbc73045fe3 100644 --- a/tooling/nargo_fmt/tests/expected/infix.nr +++ b/tooling/nargo_fmt/tests/expected/infix.nr @@ -1,3 +1,4 @@ +//@error_on_lost_comment=false fn foo() { 40 + 2; !40 + 2; @@ -6,3 +7,12 @@ fn foo() { 40/*test*/ + 2 == 42; 40 + 2/*test*/ == 42; } + +fn big() { + 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)); +} diff --git a/tooling/nargo_fmt/tests/expected/let.nr b/tooling/nargo_fmt/tests/expected/let.nr index dccdb76328c..b60ae644790 100644 --- a/tooling/nargo_fmt/tests/expected/let.nr +++ b/tooling/nargo_fmt/tests/expected/let.nr @@ -1,25 +1,21 @@ +//@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] = [// Padded hash - 209, 50, 135, 178, 4, 155, 190, 229, 228, 111, 61, 174, 8, 49, 48, 116, 90, 226, 77, 7, 111, - 27, 19, 113, 154, 48, 138, 136, 138, 15, 230, 132, 32, 4, 0, 5, 1, 2, 4, 3, 101, 1, 72, 134, - 96, 9, 6, 13, 48, 49, 48, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 0, + let padded_sha256_hash: [u8; 259] = [ + // Padded hash + 209, 50, 135, 178, 4, 155, 190, 229, 228, 111, 61, 174, 8, 49, 48, 116, 90, 226, 77, 7, 111, 27, 19, 113, 154, 48, 138, 136, 138, 15, 230, 132, 32, 4, 0, 5, 1, 2, 4, 3, 101, 1, 72, 134, 96, 9, 6, 13, 48, 49, + 48, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 0, // Rest is padded with 0s until max bytes - 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, 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, 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, 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, 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, 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, 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, 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, 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/literals.nr b/tooling/nargo_fmt/tests/expected/literals.nr index abe14c14965..5a9a735337f 100644 --- a/tooling/nargo_fmt/tests/expected/literals.nr +++ b/tooling/nargo_fmt/tests/expected/literals.nr @@ -1,3 +1,4 @@ +//@error_on_lost_comment=false fn main() { [1, 2, 3, 4, 5]; diff --git a/tooling/nargo_fmt/tests/expected/nested_parens.nr b/tooling/nargo_fmt/tests/expected/nested_parens.nr new file mode 100644 index 00000000000..53eaa63c279 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/nested_parens.nr @@ -0,0 +1,5 @@ +//@remove_nested_parens=false +fn main() { + ((())); + ((((((((())))))))); +} diff --git a/tooling/nargo_fmt/tests/expected/parens.nr b/tooling/nargo_fmt/tests/expected/parens.nr index aeba660f898..e6c4f91879c 100644 --- a/tooling/nargo_fmt/tests/expected/parens.nr +++ b/tooling/nargo_fmt/tests/expected/parens.nr @@ -1,4 +1,4 @@ -fn main(x : u64, y : pub u64) { +fn main(x: u64, y: pub u64) { ( // 1 diff --git a/tooling/nargo_fmt/tests/expected/single_fn.nr b/tooling/nargo_fmt/tests/expected/single_fn.nr new file mode 100644 index 00000000000..b02291fc50d --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/single_fn.nr @@ -0,0 +1,3 @@ +fn main() { + // hello +} diff --git a/tooling/nargo_fmt/tests/expected/single_mod.nr b/tooling/nargo_fmt/tests/expected/single_mod.nr new file mode 100644 index 00000000000..3c04a12d34b --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/single_mod.nr @@ -0,0 +1 @@ +mod hello {} diff --git a/tooling/nargo_fmt/tests/expected/struct.nr b/tooling/nargo_fmt/tests/expected/struct.nr index 6734dec68a6..cf1795892d2 100644 --- a/tooling/nargo_fmt/tests/expected/struct.nr +++ b/tooling/nargo_fmt/tests/expected/struct.nr @@ -33,7 +33,7 @@ struct MyStruct { my_int: u32, my_nest: Nested, } -fn test_struct_in_tuple(a_bool : bool,x:Field, y:Field) -> (MyStruct, bool) { +fn test_struct_in_tuple(a_bool: bool, x: Field, y: Field) -> (MyStruct, bool) { let my_struct = MyStruct { my_bool: a_bool, my_int: 5, my_nest: Nested { a: x, b: y } }; (my_struct, a_bool) } diff --git a/tooling/nargo_fmt/tests/expected/submodule.nr b/tooling/nargo_fmt/tests/expected/submodule.nr new file mode 100644 index 00000000000..88e005b7ac2 --- /dev/null +++ b/tooling/nargo_fmt/tests/expected/submodule.nr @@ -0,0 +1,30 @@ +mod a { + // hello +} + +mod a { + // hello + mod b { + // hello + } +} + +mod a { + mod b { + mod c {} + } +} + +mod a { + // 1 + // 2 + // 3 + /*test*/ +} + +mod a { + /**/ + mod b { + mod c {} + } +} diff --git a/tooling/nargo_fmt/tests/expected/tuple.nr b/tooling/nargo_fmt/tests/expected/tuple.nr index b190a5f7c55..c3b32904f15 100644 --- a/tooling/nargo_fmt/tests/expected/tuple.nr +++ b/tooling/nargo_fmt/tests/expected/tuple.nr @@ -23,7 +23,7 @@ fn main() { (/*1*/ 1, /*2*/ 2); -// FIXME: + // FIXME: (((//2 1,),),); (/*a*/ diff --git a/tooling/nargo_fmt/tests/expected/unary_operators.nr b/tooling/nargo_fmt/tests/expected/unary_operators.nr index 1dd5e4ab945..ffea1713c06 100644 --- a/tooling/nargo_fmt/tests/expected/unary_operators.nr +++ b/tooling/nargo_fmt/tests/expected/unary_operators.nr @@ -1,3 +1,4 @@ +//@error_on_lost_comment=false fn main() { -1; -/*test*/1; diff --git a/tooling/nargo_fmt/tests/input/call.nr b/tooling/nargo_fmt/tests/input/call.nr index 24e61c806cc..2e9a612e6d8 100644 --- a/tooling/nargo_fmt/tests/input/call.nr +++ b/tooling/nargo_fmt/tests/input/call.nr @@ -42,4 +42,6 @@ fn foo() { assert( x, "message" ); assert( x == y ); + + assert(p4_affine.eq(Gaffine::new(6890855772600357754907169075114257697580319025794532037257385534741338397365, 4338620300185947561074059802482547481416142213883829469920100239455078257889))); } diff --git a/tooling/nargo_fmt/tests/input/contract.nr b/tooling/nargo_fmt/tests/input/contract.nr new file mode 100644 index 00000000000..6bc5c552110 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/contract.nr @@ -0,0 +1,76 @@ +// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +// Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +// Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. +// Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +contract Benchmarking { + use dep::value_note::{ + utils::{increment, decrement}, + value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}, + }; + + use dep::aztec::{ + context::{Context}, + note::{utils as note_utils, note_getter_options::NoteGetterOptions, note_header::NoteHeader}, + selector::compute_selector, + log::emit_unencrypted_log, + state_vars::{map::Map, public_state::PublicState, set::Set}, + types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, + types::address::{AztecAddress}, + }; + + struct Storage { + notes: Map>, + balances: Map>, + } + + impl Storage { + fn init(context: Context) -> pub Self { + Storage { + notes: Map::new(context, 1, |context, slot| { Set::new(context, slot, ValueNoteMethods) }), + balances: Map::new(context, 2, |context, slot| { PublicState::new(context, slot, FieldSerializationMethods) }), + } + } + } + + #[aztec(private)] + fn constructor() {} + + // Nec tincidunt praesent semper feugiat nibh sed pulvinar. Nibh nisl condimentum id venenatis a. + #[aztec(private)] + fn create_note(owner: Field, value: Field) { + increment(storage.notes.at(owner), value, owner); + } + + // Diam quam nulla porttitor massa id. Elit ullamcorper dignissim cras tincidunt lobortis feugiat. + #[aztec(private)] + fn recreate_note(owner: Field, index: u32) { + let owner_notes = storage.notes.at(owner); + let getter_options = NoteGetterOptions::new().set_limit(1).set_offset(index); + let notes = owner_notes.get_notes(getter_options); + let note = notes[0].unwrap_unchecked(); + owner_notes.remove(note); + increment(owner_notes, note.value, owner); + } + + // Ultrices in iaculis nunc sed augue lacus. + #[aztec(public)] + 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(), compute_selector("broadcast(Field)"), [owner]); + } + + // Est ultricies integer quis auctor elit sed. In nibh mauris cursus mattis molestie a iaculis. + #[aztec(public)] + fn broadcast(owner: Field) { + 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] { + let note_header = NoteHeader::new(contract_address, nonce, storage_slot); + note_utils::compute_note_hash_and_nullifier(ValueNoteMethods, note_header, preimage) + } +} + +// Uses the token bridge contract, which tells which input token we need to talk to and handles the exit funds to L1 +contract Uniswap {} diff --git a/tooling/nargo_fmt/tests/input/expr.nr b/tooling/nargo_fmt/tests/input/expr.nr index 28ba9cb0585..b4edcbbed5f 100644 --- a/tooling/nargo_fmt/tests/input/expr.nr +++ b/tooling/nargo_fmt/tests/input/expr.nr @@ -81,6 +81,24 @@ fn test() { 34 } +fn line() { + 42; // 42 +} + + +fn line() { + 42;// 42 + 42; +// hello +} + + +fn line() { + 42;// 42 + // 42 +// hello +} + fn parenthesized() { value + ( x as Field ) } diff --git a/tooling/nargo_fmt/tests/input/fn.nr b/tooling/nargo_fmt/tests/input/fn.nr index 89484dc83c2..f503db99853 100644 --- a/tooling/nargo_fmt/tests/input/fn.nr +++ b/tooling/nargo_fmt/tests/input/fn.nr @@ -1 +1,26 @@ fn main(x: pub u8, y: u8) {} + +fn main(x: pub u8, y: u8) -> pub Field {} + +fn main(x: A, y: B) -> pub Field where A: Eq, B: Eq {} + +fn main() +// hello +{} + +fn main( + // hello +) {} + +fn main( + // hello + unit: () +) {} + +fn main() where T: Eq {} + +fn main(tape: [Field; TAPE_LEN], initial_registers: [Field; REGISTER_COUNT], initial_memory: [Field; MEM_COUNT], initial_program_counter: Field, initial_call_stack: [Field; MAX_CALL_STACK], 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 main() -> distinct pub [Field;2] {} diff --git a/tooling/nargo_fmt/tests/input/for.nr b/tooling/nargo_fmt/tests/input/for.nr new file mode 100644 index 00000000000..99b796df820 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/for.nr @@ -0,0 +1,24 @@ +fn for_stmt() { + for elem in self { + ret &= predicate(elem); + } +} + +fn for_stmt() { + for i in 0..(C1-1) { + + for _j in 1..(C1-i-1) { + + b *= b; + + } + + z *= if b == 1 { 1 } else { c }; + + c *= c; + + t *= if b == 1 { 1 } else { c }; + + b = t; + } +} diff --git a/tooling/nargo_fmt/tests/input/global.nr b/tooling/nargo_fmt/tests/input/global.nr new file mode 100644 index 00000000000..bf023c61805 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/global.nr @@ -0,0 +1,17 @@ +//! Super module :] + +// super global variable +global answer = 42; + +// Super module :] + + + + + + + + + +// super global variable +global answer = 42; diff --git a/tooling/nargo_fmt/tests/input/if.nr b/tooling/nargo_fmt/tests/input/if.nr index 0985928396d..be72eb79a18 100644 --- a/tooling/nargo_fmt/tests/input/if.nr +++ b/tooling/nargo_fmt/tests/input/if.nr @@ -1,4 +1,9 @@ +//@error_on_lost_comment=false fn main() { + let (x,y) = if is_square(gx1) {(x1, sqrt(gx1))} else {(x2, sqrt(gx2))}; + + let n = if x != y { if x != 20 { slice.push_back(y) } else { slice } } else { slice }; + if false { (); diff --git a/tooling/nargo_fmt/tests/input/ignore.nr b/tooling/nargo_fmt/tests/input/ignore.nr new file mode 100644 index 00000000000..e095d2e9f1f --- /dev/null +++ b/tooling/nargo_fmt/tests/input/ignore.nr @@ -0,0 +1,27 @@ +fn main() { + // noir-fmt:ignore + assert( x != y ); + assert( x != y ); + { + // noir-fmt:ignore + }; + assert( x != y ); +} +// noir-fmt:ignore +fn main() { +1; +2; +3; +} +// noir-fmt:ignore +mod items { +fn hello() {} +} + +fn mk_array() { + // noir-fmt:ignore + let array = [1, + ]; + let array = [1, + ]; +} diff --git a/tooling/nargo_fmt/tests/input/infix.nr b/tooling/nargo_fmt/tests/input/infix.nr index df57f956097..059e58c6b64 100644 --- a/tooling/nargo_fmt/tests/input/infix.nr +++ b/tooling/nargo_fmt/tests/input/infix.nr @@ -1,3 +1,4 @@ +//@error_on_lost_comment=false fn foo() { 40 + 2; !40+2; @@ -6,3 +7,7 @@ fn foo() { 40/*test*/ + 2 == 42; 40 + 2/*test*/ == 42; } + +fn big() { + 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)); +} diff --git a/tooling/nargo_fmt/tests/input/let.nr b/tooling/nargo_fmt/tests/input/let.nr index ae23f0150d9..67c4ab8bd52 100644 --- a/tooling/nargo_fmt/tests/input/let.nr +++ b/tooling/nargo_fmt/tests/input/let.nr @@ -1,3 +1,4 @@ +//@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 array = [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]], [[13, 14, 15], [16, 17, 18]]]; diff --git a/tooling/nargo_fmt/tests/input/literals.nr b/tooling/nargo_fmt/tests/input/literals.nr index 3490c1e7d0d..fbdc7676845 100644 --- a/tooling/nargo_fmt/tests/input/literals.nr +++ b/tooling/nargo_fmt/tests/input/literals.nr @@ -1,4 +1,4 @@ - +//@error_on_lost_comment=false fn main() { [1,2,3,4,5]; diff --git a/tooling/nargo_fmt/tests/input/nested_parens.nr b/tooling/nargo_fmt/tests/input/nested_parens.nr new file mode 100644 index 00000000000..53eaa63c279 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/nested_parens.nr @@ -0,0 +1,5 @@ +//@remove_nested_parens=false +fn main() { + ((())); + ((((((((())))))))); +} diff --git a/tooling/nargo_fmt/tests/input/single_fn.nr b/tooling/nargo_fmt/tests/input/single_fn.nr new file mode 100644 index 00000000000..c7ee3bbd3aa --- /dev/null +++ b/tooling/nargo_fmt/tests/input/single_fn.nr @@ -0,0 +1,3 @@ +fn main() { + // hello +} \ No newline at end of file diff --git a/tooling/nargo_fmt/tests/input/single_mod.nr b/tooling/nargo_fmt/tests/input/single_mod.nr new file mode 100644 index 00000000000..f02dbfb5464 --- /dev/null +++ b/tooling/nargo_fmt/tests/input/single_mod.nr @@ -0,0 +1 @@ +mod hello {} \ No newline at end of file diff --git a/tooling/nargo_fmt/tests/input/submodule.nr b/tooling/nargo_fmt/tests/input/submodule.nr new file mode 100644 index 00000000000..d5b162fd28d --- /dev/null +++ b/tooling/nargo_fmt/tests/input/submodule.nr @@ -0,0 +1,25 @@ +mod a { +// hello +} + +mod a { +// hello + mod b { +// hello + } +} + +mod a {mod b {mod c {}}} + +mod a { +// 1 +// 2 +// 3 +/*test*/ +} + +mod a { + /**/ mod b { + mod c {} + } +} diff --git a/tooling/nargo_fmt/tests/input/unary_operators.nr b/tooling/nargo_fmt/tests/input/unary_operators.nr index e6d42456ef2..4324b8045cc 100644 --- a/tooling/nargo_fmt/tests/input/unary_operators.nr +++ b/tooling/nargo_fmt/tests/input/unary_operators.nr @@ -1,3 +1,4 @@ +//@error_on_lost_comment=false fn main() { -1; -/*test*/1; diff --git a/tooling/nargo_toml/Cargo.toml b/tooling/nargo_toml/Cargo.toml index d3767a0b038..c835ddd936c 100644 --- a/tooling/nargo_toml/Cargo.toml +++ b/tooling/nargo_toml/Cargo.toml @@ -17,5 +17,6 @@ serde.workspace = true thiserror.workspace = true toml.workspace = true url.workspace = true +semver = "1.0.20" [dev-dependencies] diff --git a/tooling/nargo_toml/src/errors.rs b/tooling/nargo_toml/src/errors.rs index 9abeab97b61..fdbdc317bf9 100644 --- a/tooling/nargo_toml/src/errors.rs +++ b/tooling/nargo_toml/src/errors.rs @@ -4,7 +4,8 @@ use nargo::package::PackageType; use noirc_frontend::graph::CrateName; use thiserror::Error; -/// Errors covering situations where a package is either missing or malformed. +/// Errors covering situations where a package is either missing, malformed or does not pass semver +/// validation checks. #[derive(Debug, Error)] pub enum ManifestError { /// Package doesn't have a manifest file @@ -65,4 +66,19 @@ pub enum ManifestError { #[error("No common ancestor between {root} and {current}")] NoCommonAncestor { root: PathBuf, current: PathBuf }, + + #[error(transparent)] + SemverError(SemverError), +} + +#[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}")] + IncompatibleVersion { + package_name: CrateName, + required_compiler_version: String, + compiler_version_found: String, + }, + #[error("Could not parse the required compiler version for package {package_name} in Nargo.toml. Error: {error}")] + CouldNotParseRequiredVersion { package_name: String, error: String }, } diff --git a/tooling/nargo_toml/src/lib.rs b/tooling/nargo_toml/src/lib.rs index 5d12c09a81e..223ed2da081 100644 --- a/tooling/nargo_toml/src/lib.rs +++ b/tooling/nargo_toml/src/lib.rs @@ -18,6 +18,7 @@ use serde::Deserialize; mod errors; mod git; +mod semver; pub use errors::ManifestError; use git::clone_git_repo; @@ -163,6 +164,7 @@ impl PackageConfig { }; Ok(Package { + compiler_required_version: self.package.compiler_version.clone(), root_dir: root_dir.to_path_buf(), entry_path, package_type, @@ -228,7 +230,7 @@ struct PackageMetadata { entry: Option, description: Option, authors: Option>, - // If not compiler version is supplied, the latest is used + // If no compiler version is supplied, the latest is used // For now, we state that all packages must be compiled under the same // compiler version. // We also state that ACIR and the compiler will upgrade in lockstep. @@ -391,10 +393,14 @@ pub enum PackageSelection { pub fn resolve_workspace_from_toml( toml_path: &Path, package_selection: PackageSelection, + current_compiler_version: Option, ) -> Result { let nargo_toml = read_toml(toml_path)?; - - toml_to_workspace(nargo_toml, package_selection) + 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)?; + } + Ok(workspace) } #[test] @@ -404,7 +410,7 @@ fn parse_standard_toml() { [package] name = "test" authors = ["kev", "foo"] - compiler_version = "0.1" + compiler_version = "*" [dependencies] rand = { tag = "next", git = "https://github.com/rust-lang-nursery/rand"} @@ -422,7 +428,7 @@ fn parse_package_toml_no_deps() { [package] name = "test" authors = ["kev", "foo"] - compiler_version = "0.1" + compiler_version = "*" "#; assert!(Config::try_from(String::from(src)).is_ok()); diff --git a/tooling/nargo_toml/src/semver.rs b/tooling/nargo_toml/src/semver.rs new file mode 100644 index 00000000000..de722f06bd8 --- /dev/null +++ b/tooling/nargo_toml/src/semver.rs @@ -0,0 +1,196 @@ +use crate::{errors::SemverError, ManifestError}; +use nargo::{ + package::{Dependency, Package}, + workspace::Workspace, +}; +use semver::{Version, VersionReq}; + +// Check that all of the packages in the workspace are compatible with the current compiler version +pub(crate) fn semver_check_workspace( + workspace: Workspace, + current_compiler_version: String, +) -> Result<(), ManifestError> { + let version = Version::parse(¤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)?; + } + + Ok(()) +} + +// Check that a package and all of its dependencies are compatible with the current compiler version +pub(crate) fn semver_check_package( + package: &Package, + compiler_version: &Version, +) -> Result<(), SemverError> { + // Check that this package's compiler version requirements are satisfied + if let Some(version) = &package.compiler_required_version { + let version_req = match VersionReq::parse(version) { + Ok(version_req) => version_req, + Err(err) => { + return Err(SemverError::CouldNotParseRequiredVersion { + package_name: package.name.clone().into(), + error: err.to_string(), + }) + } + }; + if !version_req.matches(compiler_version) { + return Err(SemverError::IncompatibleVersion { + package_name: package.name.clone(), + required_compiler_version: version.clone(), + compiler_version_found: strip_build_meta_data(compiler_version), + }); + }; + } + + // Check that all of this package's dependencies' compiler version requirements are satisfied + for dep in package.dependencies.values() { + match dep { + Dependency::Local { package } | Dependency::Remote { package } => { + semver_check_package(package, compiler_version)?; + } + } + } + + Ok(()) +} + +// Strip the build meta data from the version string since it is ignored by semver. +fn strip_build_meta_data(version: &Version) -> String { + let version_string = version.to_string(); + let mut split = version_string.split('+'); + split.next().expect("split was called on an empty string").to_string() +} + +#[cfg(test)] +mod tests { + use std::{collections::BTreeMap, path::PathBuf, str::FromStr}; + + use nargo::package::PackageType; + use noirc_frontend::graph::CrateName; + + use super::*; + + #[test] + fn test_semver_check_smoke() { + let compiler_version = Version::parse("0.1.0").unwrap(); + + let mut package = Package { + compiler_required_version: Some("0.1.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("test").unwrap(), + dependencies: BTreeMap::new(), + }; + 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:?}") + }; + + package.compiler_required_version = Some("0.2.0".to_string()); + let got_err = match semver_check_package(&package, &compiler_version) { + Ok(_) => panic!("semver check should have failed. compiler version is 0.1.0 and required version from the package is 0.2.0"), + Err(err) => err, + }; + + let expected_version_error = SemverError::IncompatibleVersion { + package_name: CrateName::from_str("test").unwrap(), + required_compiler_version: "0.2.0".to_string(), + compiler_version_found: "0.1.0".to_string(), + }; + assert_eq!(got_err, expected_version_error); + } + + #[test] + fn test_semver_dependency_check_smoke() { + let compiler_version = Version::parse("0.1.0").unwrap(); + + let mut package = Package { + compiler_required_version: Some("0.1.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("test").unwrap(), + dependencies: BTreeMap::new(), + }; + + let valid_dependency = Package { + compiler_required_version: Some("0.1.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("good_dependency").unwrap(), + dependencies: BTreeMap::new(), + }; + let invalid_dependency = Package { + compiler_required_version: Some("0.2.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("bad_dependency").unwrap(), + dependencies: BTreeMap::new(), + }; + + package.dependencies.insert( + CrateName::from_str("test_dep_valid").unwrap(), + Dependency::Local { package: valid_dependency.clone() }, + ); + + 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:?}") + }; + + package.dependencies.insert( + CrateName::from_str("test_dep_invalid").unwrap(), + Dependency::Local { package: invalid_dependency.clone() }, + ); + let got_err = match semver_check_package(&package,&compiler_version) { + Ok(_) => panic!("semver check should have failed. compiler version is 0.1.0 and required version from the package is 0.2.0"), + Err(err) => err, + }; + + let expected_version_error = SemverError::IncompatibleVersion { + package_name: CrateName::from_str("bad_dependency").unwrap(), + required_compiler_version: "0.2.0".to_string(), + compiler_version_found: "0.1.0".to_string(), + }; + assert_eq!(got_err, expected_version_error); + } + + #[test] + fn test_semver_carrot() { + let compiler_version = Version::parse("0.2.0").unwrap(); + + let package = Package { + compiler_required_version: Some(">=0.1.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("test").unwrap(), + dependencies: BTreeMap::new(), + }; + + if let Err(err) = semver_check_package(&package, &compiler_version) { + panic!("semver check should have passed. compiler version is 0.2.0 and required version from the package is >=0.1.0\n error: {err:?}") + }; + } + + #[test] + fn test_semver_build_data() { + let compiler_version = Version::parse("0.1.0+this-is-ignored-by-semver").unwrap(); + + let package = Package { + compiler_required_version: Some("0.1.0".to_string()), + root_dir: PathBuf::new(), + package_type: PackageType::Library, + entry_path: PathBuf::new(), + name: CrateName::from_str("test").unwrap(), + dependencies: BTreeMap::new(), + }; + + if let Err(err) = semver_check_package(&package, &compiler_version) { + panic!("semver check should have passed. compiler version is 0.1.0+build_data and required version from the package is 0.1.0\n The build data should be ignored\n error: {err:?}") + }; + } +} diff --git a/tooling/noir_codegen/.eslintignore b/tooling/noir_codegen/.eslintignore new file mode 100644 index 00000000000..491fc35975b --- /dev/null +++ b/tooling/noir_codegen/.eslintignore @@ -0,0 +1,2 @@ +node_modules +lib diff --git a/tooling/noir_codegen/.eslintrc.cjs b/tooling/noir_codegen/.eslintrc.cjs new file mode 100644 index 00000000000..33335c2a877 --- /dev/null +++ b/tooling/noir_codegen/.eslintrc.cjs @@ -0,0 +1,3 @@ +module.exports = { + extends: ["../../.eslintrc.js"], +}; diff --git a/tooling/noir_codegen/.gitignore b/tooling/noir_codegen/.gitignore new file mode 100644 index 00000000000..721d05448d6 --- /dev/null +++ b/tooling/noir_codegen/.gitignore @@ -0,0 +1,4 @@ +crs +lib + +!test/*/target diff --git a/tooling/noir_codegen/.mocharc.json b/tooling/noir_codegen/.mocharc.json new file mode 100644 index 00000000000..82855d2ddf4 --- /dev/null +++ b/tooling/noir_codegen/.mocharc.json @@ -0,0 +1,11 @@ +{ + "require": "ts-node/register", + "loader": "ts-node/esm", + "extensions": [ + "ts", + "cjs" + ], + "spec": [ + "test/**/*.test.ts*" + ] +} \ No newline at end of file diff --git a/tooling/noir_codegen/README.md b/tooling/noir_codegen/README.md new file mode 100644 index 00000000000..c24c12ff987 --- /dev/null +++ b/tooling/noir_codegen/README.md @@ -0,0 +1,4 @@ + +## Acknowledgements + +`noir-codegen` repurposes the CLI code from https://github.com/dethcrypto/TypeChain, used under the MIT license. \ No newline at end of file diff --git a/tooling/noir_codegen/package.json b/tooling/noir_codegen/package.json new file mode 100644 index 00000000000..17772461dff --- /dev/null +++ b/tooling/noir_codegen/package.json @@ -0,0 +1,53 @@ +{ + "name": "@noir-lang/noir_codegen", + "collaborators": [ + "The Noir Team " + ], + "version": "0.19.2", + "packageManager": "yarn@3.5.1", + "license": "(MIT OR Apache-2.0)", + "type": "module", + "dependencies": { + "@noir-lang/types": "workspace:*", + "glob": "^10.3.10", + "lodash": "^4.17.21", + "ts-command-line-args": "^2.5.1" + }, + "files": [ + "lib", + "package.json" + ], + "source": "src/index.ts", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "bin": { + "noir-codegen": "lib/main.js" + }, + "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:node": "mocha --timeout 25000 --exit --config ./.mocharc.json", + "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", + "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", + "clean": "rm -rf ./lib" + }, + "devDependencies": { + "@noir-lang/noir_js": "workspace:*", + "@types/chai": "^4", + "@types/lodash": "^4", + "@types/mocha": "^10.0.1", + "@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.2.2" + } +} diff --git a/tooling/noir_codegen/src/index.ts b/tooling/noir_codegen/src/index.ts new file mode 100644 index 00000000000..1f8d2d183d4 --- /dev/null +++ b/tooling/noir_codegen/src/index.ts @@ -0,0 +1,28 @@ +import { CompiledCircuit } from '@noir-lang/types'; + +const codegenImports = `import { InputMap, InputValue } from "@noir-lang/noirc_abi" +import { Noir } 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)}); + const { returnValue } = await program.execute(args); + return returnValue; +}`; + +export const codegen = (programs: [string, CompiledCircuit][]): string => { + const results = [codegenImports]; + for (const [name, program] of programs) { + results.push(codegenFunction(name, stripUnwantedFields(program))); + } + + return results.join('\n\n'); +}; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function stripUnwantedFields(value: any): CompiledCircuit { + const { abi, bytecode } = value; + return { abi, bytecode }; +} diff --git a/tooling/noir_codegen/src/main.ts b/tooling/noir_codegen/src/main.ts new file mode 100644 index 00000000000..591e7420dba --- /dev/null +++ b/tooling/noir_codegen/src/main.ts @@ -0,0 +1,47 @@ +#! /usr/bin/env node + +import { CompiledCircuit } from '@noir-lang/types'; +import fs from 'fs'; +import path from 'path'; +import { parseArgs } from './parseArgs.js'; +import { glob } from './utils/glob.js'; +import { codegen } from './index.js'; + +function main() { + const cliConfig = parseArgs(); + const cwd = process.cwd(); + + const files = getFilesToProcess(cwd, cliConfig.files); + if (files.length === 0) { + throw new Error('No files passed.' + '\n' + `\`${cliConfig.files}\` didn't match any input files in ${cwd}`); + } + + const programs = files.map((file_path): [string, CompiledCircuit] => { + const program_name = path.parse(file_path).name; + const file_contents = fs.readFileSync(file_path).toString(); + const { abi, bytecode } = JSON.parse(file_contents); + + return [program_name, { abi, bytecode }]; + }); + + const result = codegen(programs); + + const outputDir = path.resolve(cliConfig.outDir ?? './codegen'); + const outputFile = path.join(outputDir, 'index.ts'); + if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir); + fs.writeFileSync(outputFile, result); +} + +function getFilesToProcess(cwd: string, filesOrPattern: string[]) { + let res = glob(cwd, filesOrPattern); + + if (res.length === 0) { + // If there are no files found, but first parameter is surrounded with single quotes, we try again without quotes + const match = filesOrPattern[0].match(/'([\s\S]*)'/)?.[1]; + if (match) res = glob(cwd, [match]); + } + + return res; +} + +main(); diff --git a/tooling/noir_codegen/src/parseArgs.ts b/tooling/noir_codegen/src/parseArgs.ts new file mode 100644 index 00000000000..58468c1b8f8 --- /dev/null +++ b/tooling/noir_codegen/src/parseArgs.ts @@ -0,0 +1,64 @@ +import { parse as commandLineArgs } from 'ts-command-line-args'; + +const DEFAULT_GLOB_PATTERN = './target/**/*.json'; + +export interface ParsedArgs { + files: string[]; + outDir?: string | undefined; + inputDir?: string | undefined; +} + +export function parseArgs(): ParsedArgs { + const rawOptions = commandLineArgs( + { + glob: { + type: String, + defaultOption: true, + multiple: true, + defaultValue: [DEFAULT_GLOB_PATTERN], + description: + 'Pattern that will be used to find program artifacts. Remember about adding quotes: noir-codegen "**/*.json".', + }, + 'out-dir': { type: String, optional: true, description: 'Output directory for generated files.' }, + 'input-dir': { + type: String, + optional: true, + description: + 'Directory containing program artifact files. Inferred as lowest common path of all files if not specified.', + }, + help: { type: Boolean, defaultValue: false, alias: 'h', description: 'Prints this message.' }, + }, + { + helpArg: 'help', + headerContentSections: [ + { + content: `\ + noir-codegen generates TypeScript wrappers for Noir programs to simplify replicating your Noir logic in JS.`, + }, + ], + footerContentSections: [ + { + header: 'Example Usage', + content: `\ + noir-codegen --out-dir app/noir_programs './target/*.json' + + + You can read more about noir-codegen at {underline https://github.com/noir-lang/noir}.`, + }, + ], + }, + ); + + return { + files: rawOptions.glob, + outDir: rawOptions['out-dir'], + inputDir: rawOptions['input-dir'], + }; +} + +interface CommandLineArgs { + glob: string[]; + 'out-dir'?: string; + 'input-dir'?: string; + help: boolean; +} diff --git a/tooling/noir_codegen/src/utils/glob.ts b/tooling/noir_codegen/src/utils/glob.ts new file mode 100644 index 00000000000..15deaf72e44 --- /dev/null +++ b/tooling/noir_codegen/src/utils/glob.ts @@ -0,0 +1,9 @@ +import { sync as globSync } from 'glob'; +import _ from 'lodash'; +const { flatten, uniq } = _; + +export function glob(cwd: string, patternsOrFiles: string[]): string[] { + const matches = patternsOrFiles.map((p) => globSync(p, { ignore: 'node_modules/**', absolute: true, cwd })); + + return uniq(flatten(matches)); +} diff --git a/tooling/noir_codegen/test/assert_lt/Nargo.toml b/tooling/noir_codegen/test/assert_lt/Nargo.toml new file mode 100644 index 00000000000..f32ec18cae7 --- /dev/null +++ b/tooling/noir_codegen/test/assert_lt/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "assert_lt" +type = "bin" +authors = [""] +[dependencies] diff --git a/tooling/noir_codegen/test/assert_lt/src/main.nr b/tooling/noir_codegen/test/assert_lt/src/main.nr new file mode 100644 index 00000000000..0698cbce4a8 --- /dev/null +++ b/tooling/noir_codegen/test/assert_lt/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: u64, y: pub u64) -> pub u64 { + assert(x < y); + x + y +} diff --git a/tooling/noir_codegen/test/assert_lt/target/assert_lt.json b/tooling/noir_codegen/test/assert_lt/target/assert_lt.json new file mode 100644 index 00000000000..3b2b1b2c5a1 --- /dev/null +++ b/tooling/noir_codegen/test/assert_lt/target/assert_lt.json @@ -0,0 +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 diff --git a/tooling/noir_codegen/test/index.test.ts b/tooling/noir_codegen/test/index.test.ts new file mode 100644 index 00000000000..702ba1f9cbb --- /dev/null +++ b/tooling/noir_codegen/test/index.test.ts @@ -0,0 +1,11 @@ +import { expect } from 'chai'; +import { assert_lt } from './codegen/index.js'; + +it('codegens a callable function', async () => { + const result = await assert_lt({ + x: '2', + y: '3', + }); + + expect(result).to.be.eq('0x05'); +}); diff --git a/tooling/noir_codegen/tsconfig.json b/tooling/noir_codegen/tsconfig.json new file mode 100644 index 00000000000..30dd2a7ee5f --- /dev/null +++ b/tooling/noir_codegen/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "esnext", + "declaration": true, + "emitDeclarationOnly": false, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "outDir": "./lib", + "esModuleInterop": true, + "resolveJsonModule": true, + "strict": true, + "noImplicitAny": false, + }, + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/tooling/noir_js/package.json b/tooling/noir_js/package.json index 09dfac939d2..51bc7550200 100644 --- a/tooling/noir_js/package.json +++ b/tooling/noir_js/package.json @@ -3,7 +3,7 @@ "collaborators": [ "The Noir Team " ], - "version": "0.18.0", + "version": "0.19.2", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/tooling/noir_js/src/index.ts b/tooling/noir_js/src/index.ts index 3d424ca0dea..5e700a5b583 100644 --- a/tooling/noir_js/src/index.ts +++ b/tooling/noir_js/src/index.ts @@ -1,8 +1,23 @@ import * as acvm from '@noir-lang/acvm_js'; import * as abi from '@noir-lang/noirc_abi'; +import { CompiledCircuit, ProofData } from '@noir-lang/types'; -export { acvm, abi }; +export { + ecdsa_secp256r1_verify, + ecdsa_secp256k1_verify, + keccak256, + blake2s256, + sha256, + xor, + and, +} from '@noir-lang/acvm_js'; -export { WitnessMap } from '@noir-lang/acvm_js'; +export { WitnessMap, ForeignCallHandler, ForeignCallInput, ForeignCallOutput } from '@noir-lang/acvm_js'; export { Noir } from './program.js'; + +/** @ignore */ +export { acvm, abi }; + +// type exports for typedoc +export { CompiledCircuit, ProofData }; diff --git a/tooling/noir_js/src/program.ts b/tooling/noir_js/src/program.ts index bf48e15fcad..711413bbc84 100644 --- a/tooling/noir_js/src/program.ts +++ b/tooling/noir_js/src/program.ts @@ -2,7 +2,7 @@ import { Backend, CompiledCircuit, ProofData } from '@noir-lang/types'; import { generateWitness } from './witness_generation.js'; import initAbi, { abiDecode, InputMap, InputValue } from '@noir-lang/noirc_abi'; -import initACVM, { compressWitness } from '@noir-lang/acvm_js'; +import initACVM, { compressWitness, ForeignCallHandler } from '@noir-lang/acvm_js'; export class Noir { constructor( @@ -10,6 +10,7 @@ export class Noir { private backend?: Backend, ) {} + /** @ignore */ async init(): Promise { // If these are available, then we are in the // web environment. For the node environment, this @@ -19,6 +20,17 @@ export class Noir { } } + /** + * + * @description + * Destroys the underlying backend instance. + * + * @example + * ```typescript + * await noir.destroy(); + * ``` + * + */ async destroy(): Promise { await this.backend?.destroy(); } @@ -29,19 +41,53 @@ export class Noir { } // Initial inputs to your program - async execute(inputs: InputMap): Promise<{ witness: Uint8Array; returnValue: InputValue }> { + /** + * @description + * Allows to execute a circuit to get its witness and return value. + * + * @example + * ```typescript + * async execute(inputs) + * ``` + */ + async execute( + inputs: InputMap, + foreignCallHandler?: ForeignCallHandler, + ): Promise<{ witness: Uint8Array; returnValue: InputValue }> { await this.init(); - const witness = await generateWitness(this.circuit, inputs); + const witness = await generateWitness(this.circuit, inputs, foreignCallHandler); const { return_value: returnValue } = abiDecode(this.circuit.abi, witness); return { witness: compressWitness(witness), returnValue }; } - // Initial inputs to your program + /** + * + * @description + * Generates a witness and a proof given an object as input. + * + * @example + * ```typescript + * async generateFinalproof(input) + * ``` + * + */ async generateFinalProof(inputs: InputMap): Promise { const { witness } = await this.execute(inputs); return this.getBackend().generateFinalProof(witness); } + /** + * + * @description + * Instantiates the verification key and verifies a proof. + * + * + * @example + * ```typescript + * async verifyFinalProof(proof) + * ``` + * + */ async verifyFinalProof(proofData: ProofData): Promise { return this.getBackend().verifyFinalProof(proofData); } diff --git a/tooling/noir_js/src/witness_generation.ts b/tooling/noir_js/src/witness_generation.ts index f96cddb0eca..e3ddb1a2a21 100644 --- a/tooling/noir_js/src/witness_generation.ts +++ b/tooling/noir_js/src/witness_generation.ts @@ -1,19 +1,25 @@ import { abiEncode, InputMap } from '@noir-lang/noirc_abi'; import { base64Decode } from './base64_decode.js'; -import { executeCircuit, WitnessMap } from '@noir-lang/acvm_js'; +import { executeCircuit, WitnessMap, ForeignCallHandler, ForeignCallInput } from '@noir-lang/acvm_js'; import { CompiledCircuit } from '@noir-lang/types'; +const defaultForeignCallHandler: ForeignCallHandler = (name: string, args: ForeignCallInput[]) => { + throw Error(`Unexpected oracle during execution: ${name}(${args.join(', ')})`); +}; + // Generates the witnesses needed to feed into the chosen proving system -export async function generateWitness(compiledProgram: CompiledCircuit, inputs: InputMap): Promise { +export async function generateWitness( + compiledProgram: CompiledCircuit, + inputs: InputMap, + foreignCallHandler: ForeignCallHandler = defaultForeignCallHandler, +): Promise { // Throws on ABI encoding error const witnessMap = abiEncode(compiledProgram.abi, inputs); // Execute the circuit to generate the rest of the witnesses and serialize // them into a Uint8Array. try { - const solvedWitness = await executeCircuit(base64Decode(compiledProgram.bytecode), witnessMap, () => { - throw Error('unexpected oracle during execution'); - }); + const solvedWitness = await executeCircuit(base64Decode(compiledProgram.bytecode), witnessMap, foreignCallHandler); return solvedWitness; } catch (err) { throw new Error(`Circuit execution failed: ${err}`); diff --git a/tooling/noir_js/test/node/e2e.test.ts b/tooling/noir_js/test/node/e2e.test.ts index f7c3ea37a1a..33d64377b06 100644 --- a/tooling/noir_js/test/node/e2e.test.ts +++ b/tooling/noir_js/test/node/e2e.test.ts @@ -69,19 +69,7 @@ it('end-to-end proof creation and verification (inner)', async () => { expect(isValid).to.be.true; }); -// The "real" workflow will involve a prover and a verifier on different systems. -// -// We cannot do this in our tests because they will panic with: -// `unreachable` -// -// This happens when we we create a proof with one barretenberg instance and -// try to verify it with another. -// -// If this bug is fixed, we can remove this test and split barretenberg into -// a prover and verifier class to more accurately reflect what happens in production. -// -// If its not fixable, we can leave it in as documentation of this behavior. -it('[BUG] -- bb.js unreachable (different instance) ', async () => { +it('end-to-end proving and verification with different instances', async () => { // Noir.Js part const inputs = { x: '2', @@ -97,16 +85,9 @@ it('[BUG] -- bb.js unreachable (different instance) ', async () => { const proof = await prover.generateFinalProof(witness); - try { - const verifier = new Backend(assert_lt_program); - await verifier.verifyFinalProof(proof); - expect.fail( - 'bb.js currently returns a bug when we try to verify a proof with a different Barretenberg instance that created it.', - ); - } catch (error) { - const knownError = error as Error; - expect(knownError.message).to.contain('unreachable'); - } + const verifier = new Backend(assert_lt_program); + const proof_is_valid = await verifier.verifyFinalProof(proof); + expect(proof_is_valid).to.be.true; }); // This bug occurs when we use the same backend to create an inner proof and then an outer proof diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_lt/Nargo.toml b/tooling/noir_js/test/noir_compiled_examples/assert_lt/Nargo.toml index 742f100681f..f32ec18cae7 100644 --- a/tooling/noir_js/test/noir_compiled_examples/assert_lt/Nargo.toml +++ b/tooling/noir_js/test/noir_compiled_examples/assert_lt/Nargo.toml @@ -2,6 +2,4 @@ name = "assert_lt" type = "bin" authors = [""] -compiler_version = "0.1" - [dependencies] 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 8deda68c051..0698cbce4a8 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,4 @@ -fn main(x : u64, y : pub u64) -> pub u64 { - assert(x < y); - x + y +fn main(x: u64, y: pub u64) -> pub u64 { + 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 3b2b1b2c5a1..c01b2c5d3f5 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":[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 +{"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 diff --git a/tooling/noir_js/tsconfig.json b/tooling/noir_js/tsconfig.json index 1e0fdea09c7..0dbc5204556 100644 --- a/tooling/noir_js/tsconfig.json +++ b/tooling/noir_js/tsconfig.json @@ -2,7 +2,6 @@ "compilerOptions": { "target": "esnext", "declaration": true, - "emitDeclarationOnly": false, "module": "ESNext", "moduleResolution": "node", "outDir": "./lib", @@ -12,5 +11,10 @@ "noImplicitAny": false, }, "include": ["src/**/*.ts"], - "exclude": ["node_modules"] -} \ No newline at end of file + "exclude": ["node_modules"], + "references": [ + { + "path": "../noir_js_types" + }, + ] +} diff --git a/tooling/noir_js_backend_barretenberg/package.json b/tooling/noir_js_backend_barretenberg/package.json index 3dbfb52a7f8..13c64dc1d65 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.18.0", + "version": "0.19.2", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", @@ -32,7 +32,7 @@ "lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0" }, "dependencies": { - "@aztec/bb.js": "0.11.0", + "@aztec/bb.js": "0.12.0", "@noir-lang/types": "workspace:*", "fflate": "^0.8.0" }, diff --git a/tooling/noir_js_backend_barretenberg/src/index.ts b/tooling/noir_js_backend_barretenberg/src/index.ts index 11c56a7384d..820cda93c83 100644 --- a/tooling/noir_js_backend_barretenberg/src/index.ts +++ b/tooling/noir_js_backend_barretenberg/src/index.ts @@ -25,6 +25,7 @@ export class BarretenbergBackend implements Backend { this.acirUncompressedBytecode = acirToUint8Array(acirBytecodeBase64); } + /** @ignore */ async instantiate(): Promise { if (!this.api) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -38,6 +39,7 @@ export class BarretenbergBackend implements Backend { await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data())); this.acirComposer = await api.acirNewAcirComposer(subgroupSize); + await api.acirInitProvingKey(this.acirComposer, this.acirUncompressedBytecode); this.api = api; } } @@ -63,11 +65,20 @@ export class BarretenbergBackend implements Backend { // We set `makeEasyToVerifyInCircuit` to true, which will tell the backend to // generate the proof using components that will make the proof // easier to verify in a circuit. + + /** + * + * @example + * ```typescript + * const intermediateProof = await backend.generateIntermediateProof(witness); + * ``` + */ async generateIntermediateProof(witness: Uint8Array): Promise { const makeEasyToVerifyInCircuit = true; return this.generateProof(witness, makeEasyToVerifyInCircuit); } + /** @ignore */ async generateProof(compressedWitness: Uint8Array, makeEasyToVerifyInCircuit: boolean): Promise { await this.instantiate(); const proofWithPublicInputs = await this.api.acirCreateProof( @@ -103,6 +114,14 @@ export class BarretenbergBackend implements Backend { // method. // // The number of public inputs denotes how many public inputs are in the inner proof. + + /** + * + * @example + * ```typescript + * const artifacts = await backend.generateIntermediateProofArtifacts(proof, numOfPublicInputs); + * ``` + */ async generateIntermediateProofArtifacts( proofData: ProofData, numOfPublicInputs = 0, @@ -136,12 +155,20 @@ export class BarretenbergBackend implements Backend { return verified; } + /** + * + * @example + * ```typescript + * const isValidIntermediate = await backend.verifyIntermediateProof(proof); + * ``` + */ async verifyIntermediateProof(proofData: ProofData): Promise { const proof = reconstructProofWithPublicInputs(proofData); const makeEasyToVerifyInCircuit = true; return this.verifyProof(proof, makeEasyToVerifyInCircuit); } + /** @ignore */ async verifyProof(proof: Uint8Array, makeEasyToVerifyInCircuit: boolean): Promise { await this.instantiate(); await this.api.acirInitVerificationKey(this.acirComposer); @@ -178,3 +205,6 @@ function flattenUint8Arrays(arrays: Uint8Array[]): Uint8Array { return result; } + +// typedoc exports +export { Backend, BackendOptions, CompiledCircuit, ProofData }; diff --git a/tooling/noir_js_backend_barretenberg/src/types.ts b/tooling/noir_js_backend_barretenberg/src/types.ts index b88a942d986..041e36fdf91 100644 --- a/tooling/noir_js_backend_barretenberg/src/types.ts +++ b/tooling/noir_js_backend_barretenberg/src/types.ts @@ -1,3 +1,8 @@ +/** + * @description + * An options object, currently only used to specify the number of threads to use. + */ export type BackendOptions = { + /** @description Number of threads */ threads: number; }; diff --git a/tooling/noir_js_backend_barretenberg/tsconfig.json b/tooling/noir_js_backend_barretenberg/tsconfig.json index 393fa38f583..1e28c044bba 100644 --- a/tooling/noir_js_backend_barretenberg/tsconfig.json +++ b/tooling/noir_js_backend_barretenberg/tsconfig.json @@ -12,5 +12,10 @@ "noImplicitAny": false, }, "include": ["src/**/*.ts"], - "exclude": ["node_modules"] + "exclude": ["node_modules"], + "references": [ + { + "path": "../noir_js_types" + } + ] } diff --git a/tooling/noir_js_types/.gitignore b/tooling/noir_js_types/.gitignore index 7951405f85a..e92523b6247 100644 --- a/tooling/noir_js_types/.gitignore +++ b/tooling/noir_js_types/.gitignore @@ -1 +1,3 @@ -lib \ No newline at end of file +lib + +*.tsbuildinfo diff --git a/tooling/noir_js_types/package.json b/tooling/noir_js_types/package.json index 06f7ce41d1f..3d74d335162 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.18.0", + "version": "0.19.2", "license": "(MIT OR Apache-2.0)", "files": [ "lib", diff --git a/tooling/noir_js_types/src/types.ts b/tooling/noir_js_types/src/types.ts index f534ec9a920..5ed6b1721e9 100644 --- a/tooling/noir_js_types/src/types.ts +++ b/tooling/noir_js_types/src/types.ts @@ -1,25 +1,60 @@ import { Abi } from '@noir-lang/noirc_abi'; export interface Backend { - // Generate an outer proof. This is the proof for the circuit which will verify - // inner proofs and or can be seen as the proof created for regular circuits. + /** + * @description Generates a final proof (not meant to be verified in another circuit) */ generateFinalProof(decompressedWitness: Uint8Array): Promise; - // Generates an inner proof. This is the proof that will be verified - // in another circuit. + /** + * @description Generates an intermediate proof (meant to be verified in another circuit) */ generateIntermediateProof(decompressedWitness: Uint8Array): Promise; + /** + * + * @description Retrieves the artifacts from a proof in the Field format + */ + generateIntermediateProofArtifacts( + proofData: ProofData, + numOfPublicInputs: number, + ): Promise<{ + /** @description An array of Fields containing the proof */ + proofAsFields: string[]; + /** @description An array of Fields containing the verification key */ + vkAsFields: string[]; + /** @description A Field containing the verification key hash */ + vkHash: string; + }>; + + /** + * @description Verifies a final proof */ verifyFinalProof(proofData: ProofData): Promise; + + /** @description Verifies an intermediate proof */ verifyIntermediateProof(proofData: ProofData): Promise; + + /** + * @description Destroys the backend */ destroy(): Promise; } +/** + * @description + * The representation of a proof + * */ export type ProofData = { + /** @description Public inputs of a proof */ publicInputs: Uint8Array[]; + /** @description An byte array representing the proof */ proof: Uint8Array; }; +/** + * @description + * The representation of a compiled circuit + * */ export type CompiledCircuit = { + /** @description The bytecode of the circuit */ bytecode: string; + /** @description ABI representation of the circuit */ abi: Abi; }; diff --git a/tooling/noir_js_types/tsconfig.json b/tooling/noir_js_types/tsconfig.json index 1fe2a46abaa..0d5441cc5a2 100644 --- a/tooling/noir_js_types/tsconfig.json +++ b/tooling/noir_js_types/tsconfig.json @@ -1,12 +1,13 @@ { "compilerOptions": { + "composite": true, "declaration": true, "module": "ESNext", "moduleResolution": "node", "outDir": "lib/esm", "target": "ES2020", - "rootDir": "./src" + "rootDir": "./src", }, "include": ["src/**/*.ts"], "exclude": ["node_modules"] -} \ No newline at end of file +} diff --git a/tooling/noirc_abi/src/lib.rs b/tooling/noirc_abi/src/lib.rs index 9753dc21f14..7092f05c26e 100644 --- a/tooling/noirc_abi/src/lib.rs +++ b/tooling/noirc_abi/src/lib.rs @@ -3,8 +3,6 @@ #![warn(unreachable_pub)] #![warn(clippy::semicolon_if_nothing_returned)] -use std::{collections::BTreeMap, str}; - use acvm::{ acir::native_types::{Witness, WitnessMap}, FieldElement, @@ -16,6 +14,8 @@ use noirc_frontend::{ hir::Context, Signedness, StructType, Type, TypeBinding, TypeVariableKind, Visibility, }; use serde::{Deserialize, Serialize}; +use std::ops::Range; +use std::{collections::BTreeMap, str}; // This is the ABI used to bridge the different TOML formats for the initial // witness, the partial witness generator and the interpreter. // @@ -218,7 +218,7 @@ pub struct Abi { pub parameters: Vec, /// 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 param_witnesses: BTreeMap>>, pub return_type: Option, pub return_witnesses: Vec, } @@ -315,13 +315,14 @@ impl Abi { let mut witness_map: BTreeMap = encoded_input_map .iter() .flat_map(|(param_name, encoded_param_fields)| { - let param_witness_indices = &self.param_witnesses[param_name]; + let param_witness_indices = range_to_vec(&self.param_witnesses[param_name]); param_witness_indices .iter() .zip(encoded_param_fields.iter()) .map(|(&witness, &field_element)| (witness, field_element)) + .collect::>() }) - .collect(); + .collect::>(); // 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. @@ -398,7 +399,7 @@ impl Abi { let public_inputs_map = try_btree_map(self.parameters.clone(), |AbiParameter { name, typ, .. }| { let param_witness_values = - try_vecmap(self.param_witnesses[&name].clone(), |witness_index| { + try_vecmap(range_to_vec(&self.param_witnesses[&name]), |witness_index| { witness_map .get(&witness_index) .ok_or_else(|| AbiError::MissingParamWitnessValue { @@ -529,6 +530,16 @@ impl ContractEvent { } } +fn range_to_vec(ranges: &[Range]) -> Vec { + let mut result = Vec::new(); + for range in ranges { + for witness in range.start.witness_index()..range.end.witness_index() { + result.push(witness.into()); + } + } + result +} + #[cfg(test)] mod test { use std::collections::BTreeMap; @@ -554,8 +565,8 @@ mod test { ], // Note that the return value shares a witness with `thing2` param_witnesses: BTreeMap::from([ - ("thing1".to_string(), vec![Witness(1), Witness(2)]), - ("thing2".to_string(), vec![Witness(3)]), + ("thing1".to_string(), vec![(Witness(1)..Witness(3))]), + ("thing2".to_string(), vec![(Witness(3)..Witness(4))]), ]), return_type: Some(AbiType::Field), return_witnesses: vec![Witness(3)], diff --git a/tooling/noirc_abi_wasm/Cargo.toml b/tooling/noirc_abi_wasm/Cargo.toml index 130f022dd1f..c78c3ead0c3 100644 --- a/tooling/noirc_abi_wasm/Cargo.toml +++ b/tooling/noirc_abi_wasm/Cargo.toml @@ -18,17 +18,16 @@ iter-extended.workspace = true wasm-bindgen.workspace = true serde.workspace = true js-sys.workspace = true - -console_error_panic_hook = "0.1.7" -gloo-utils = { version = "0.1", features = ["serde"] } +console_error_panic_hook.workspace = true +gloo-utils.workspace = true # This is an unused dependency, we are adding it # so that we can enable the js feature in getrandom. -getrandom = { version = "*", features = ["js"] } +getrandom = { workspace = true, features = ["js"] } [build-dependencies] -build-data = "0.1.3" +build-data.workspace = true [dev-dependencies] -wasm-bindgen-test = "0.3.36" +wasm-bindgen-test.workspace = true diff --git a/tooling/noirc_abi_wasm/package.json b/tooling/noirc_abi_wasm/package.json index f98340f7131..d307a186a7d 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.18.0", + "version": "0.19.2", "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 ea03aa8abe7..734ca1ff40e 100644 --- a/tooling/noirc_abi_wasm/src/lib.rs +++ b/tooling/noirc_abi_wasm/src/lib.rs @@ -57,7 +57,7 @@ export type AbiType = { kind: "array", length: number, type: AbiType } | { kind: "tuple", fields: AbiType[] } | { kind: "struct", path: string, fields: [string, AbiType][] }; - + export type AbiParameter = { name: string, type: AbiType, @@ -66,7 +66,7 @@ export type AbiParameter = { export type Abi = { parameters: AbiParameter[], - param_witnesses: Record, + param_witnesses: Record, return_type: AbiType | null, return_witnesses: number[], } diff --git a/tooling/noirc_abi_wasm/test/shared/abi_encode.ts b/tooling/noirc_abi_wasm/test/shared/abi_encode.ts index 28379745dec..cb80c6710ba 100644 --- a/tooling/noirc_abi_wasm/test/shared/abi_encode.ts +++ b/tooling/noirc_abi_wasm/test/shared/abi_encode.ts @@ -9,7 +9,7 @@ export const abi: Abi = { visibility: 'private', }, ], - param_witnesses: { foo: [1], bar: [2, 3] }, + param_witnesses: { foo: [{ start: 1, end: 2 }], bar: [{ start: 2, end: 4 }] }, return_type: null, return_witnesses: [], }; diff --git a/tooling/noirc_abi_wasm/test/shared/array_as_field.ts b/tooling/noirc_abi_wasm/test/shared/array_as_field.ts index ba58f075702..0cc0035fa68 100644 --- a/tooling/noirc_abi_wasm/test/shared/array_as_field.ts +++ b/tooling/noirc_abi_wasm/test/shared/array_as_field.ts @@ -8,7 +8,7 @@ export const abi: Abi = { visibility: 'private', }, ], - param_witnesses: { foo: [1, 2] }, + param_witnesses: { foo: [{ start: 1, end: 3 }] }, return_type: null, return_witnesses: [], }; diff --git a/tooling/noirc_abi_wasm/test/shared/field_as_array.ts b/tooling/noirc_abi_wasm/test/shared/field_as_array.ts index 931720d5e1b..6ae709459de 100644 --- a/tooling/noirc_abi_wasm/test/shared/field_as_array.ts +++ b/tooling/noirc_abi_wasm/test/shared/field_as_array.ts @@ -8,7 +8,7 @@ export const abi: Abi = { visibility: 'private', }, ], - param_witnesses: { foo: [1, 2] }, + param_witnesses: { foo: [{ start: 1, end: 3 }] }, return_type: null, return_witnesses: [], }; diff --git a/tooling/noirc_abi_wasm/test/shared/uint_overflow.ts b/tooling/noirc_abi_wasm/test/shared/uint_overflow.ts index ee87e050b23..c6e066e2bcd 100644 --- a/tooling/noirc_abi_wasm/test/shared/uint_overflow.ts +++ b/tooling/noirc_abi_wasm/test/shared/uint_overflow.ts @@ -8,7 +8,7 @@ export const abi: Abi = { visibility: 'private', }, ], - param_witnesses: { foo: [1] }, + param_witnesses: { foo: [{ start: 1, end: 2 }] }, return_type: null, return_witnesses: [], }; diff --git a/tooling/readme.md b/tooling/readme.md new file mode 100644 index 00000000000..20d1b560b5b --- /dev/null +++ b/tooling/readme.md @@ -0,0 +1,15 @@ +# Structure + +Below we briefly describe the purpose of each tool-related crate in this repository. + +## nargo + +This is the default package manager used by Noir. One may draw similarities to Rusts' Cargo. + +## nargo_fmt + +This is the default formatter used by Noir, analogous to Rust's rustfmt. + +## lsp + +This is the platform agnostic implementation of Noir's Language Server. It implements the various features supported, but doesn't bind to any particular transport. Binding to a transport must be done when consuming the crate. diff --git a/yarn.lock b/yarn.lock index fa4a28d9988..87713e1f915 100644 --- a/yarn.lock +++ b/yarn.lock @@ -221,9 +221,9 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@npm:0.11.0": - version: 0.11.0 - resolution: "@aztec/bb.js@npm:0.11.0" +"@aztec/bb.js@npm:0.12.0": + version: 0.12.0 + resolution: "@aztec/bb.js@npm:0.12.0" dependencies: comlink: ^4.4.1 commander: ^10.0.1 @@ -231,7 +231,7 @@ __metadata: tslib: ^2.4.0 bin: bb.js: dest/node/main.js - checksum: fff6813458dfa654210859dbf32abcb6c520ef8b3c4896535afa1bbc4a1a6dc77fd5626051fe0017de2f4b03d09bd9629fa1a144df2af3270a2e00faa779362d + checksum: d9d57b893b9b1c61949cb9bd911d4b7e1ece34965ccb9e122b39cd4e2edac9f06858abbe05c23f66141c9a74ff4861a354bfc5d62e5dcf772cfe8d1c783e2562 languageName: node linkType: hard @@ -2281,7 +2281,7 @@ __metadata: languageName: node linkType: hard -"@docusaurus/types@npm:2.4.3": +"@docusaurus/types@npm:2.4.3, @docusaurus/types@npm:^2.4.1": version: 2.4.3 resolution: "@docusaurus/types@npm:2.4.3" dependencies: @@ -3434,7 +3434,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg" dependencies: - "@aztec/bb.js": 0.11.0 + "@aztec/bb.js": 0.12.0 "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 @@ -3446,6 +3446,32 @@ __metadata: languageName: unknown linkType: soft +"@noir-lang/noir_codegen@workspace:tooling/noir_codegen": + version: 0.0.0-use.local + resolution: "@noir-lang/noir_codegen@workspace:tooling/noir_codegen" + dependencies: + "@noir-lang/noir_js": "workspace:*" + "@noir-lang/types": "workspace:*" + "@types/chai": ^4 + "@types/lodash": ^4 + "@types/mocha": ^10.0.1 + "@types/node": ^20.6.2 + "@types/prettier": ^3 + chai: ^4.3.8 + eslint: ^8.50.0 + eslint-plugin-prettier: ^5.0.0 + glob: ^10.3.10 + lodash: ^4.17.21 + mocha: ^10.2.0 + prettier: 3.0.3 + ts-command-line-args: ^2.5.1 + ts-node: ^10.9.1 + typescript: ^5.2.2 + bin: + noir-codegen: lib/main.js + languageName: unknown + linkType: soft + "@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" @@ -4640,6 +4666,13 @@ __metadata: languageName: node linkType: hard +"@types/lodash@npm:^4": + version: 4.14.200 + resolution: "@types/lodash@npm:4.14.200" + checksum: 6471f8bb5da692a6ecf03a8da4935bfbc341e67ee9bcb4f5730bfacff0c367232548f0a01e8ac5ea18c6fe78fb085d502494e33ccb47a7ee87cbdee03b47d00d + languageName: node + linkType: hard + "@types/lru-cache@npm:^5.1.0": version: 5.1.1 resolution: "@types/lru-cache@npm:5.1.1" @@ -5882,6 +5915,13 @@ __metadata: languageName: node linkType: hard +"ansi-sequence-parser@npm:^1.1.0": + version: 1.1.1 + resolution: "ansi-sequence-parser@npm:1.1.1" + checksum: ead5b15c596e8e85ca02951a844366c6776769dcc9fd1bd3a0db11bb21364554822c6a439877fb599e7e1ffa0b5f039f1e5501423950457f3dcb2f480c30b188 + languageName: node + linkType: hard + "ansi-styles@npm:^3.2.1": version: 3.2.1 resolution: "ansi-styles@npm:3.2.1" @@ -5971,6 +6011,13 @@ __metadata: languageName: node linkType: hard +"array-back@npm:^4.0.1, array-back@npm:^4.0.2": + version: 4.0.2 + resolution: "array-back@npm:4.0.2" + checksum: f30603270771eeb54e5aad5f54604c62b3577a18b6db212a7272b2b6c32049121b49431f656654790ed1469411e45f387e7627c0de8fd0515995cc40df9b9294 + languageName: node + linkType: hard + "array-back@npm:^6.2.2": version: 6.2.2 resolution: "array-back@npm:6.2.2" @@ -7271,6 +7318,18 @@ __metadata: languageName: node linkType: hard +"command-line-usage@npm:^6.1.0": + version: 6.1.3 + resolution: "command-line-usage@npm:6.1.3" + dependencies: + array-back: ^4.0.2 + chalk: ^2.4.2 + table-layout: ^1.0.2 + typical: ^5.2.0 + checksum: 8261d4e5536eb0bcddee0ec5e89c05bb2abd18e5760785c8078ede5020bc1c612cbe28eb6586f5ed4a3660689748e5aaad4a72f21566f4ef39393694e2fa1a0b + languageName: node + linkType: hard + "command-line-usage@npm:^7.0.0, command-line-usage@npm:^7.0.1": version: 7.0.1 resolution: "command-line-usage@npm:7.0.1" @@ -7966,7 +8025,7 @@ __metadata: languageName: node linkType: hard -"deep-extend@npm:^0.6.0": +"deep-extend@npm:^0.6.0, deep-extend@npm:~0.6.0": version: 0.6.0 resolution: "deep-extend@npm:0.6.0" checksum: 7be7e5a8d468d6b10e6a67c3de828f55001b6eb515d014f7aeb9066ce36bd5717161eb47d6a0f7bed8a9083935b465bc163ee2581c8b128d29bf61092fdf57a7 @@ -8233,12 +8292,18 @@ __metadata: "@mdx-js/react": ^1.6.22 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 + 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 languageName: unknown linkType: soft @@ -8251,6 +8316,17 @@ __metadata: languageName: node linkType: hard +"docusaurus-plugin-typedoc@npm:1.0.0-next.18": + version: 1.0.0-next.18 + resolution: "docusaurus-plugin-typedoc@npm:1.0.0-next.18" + dependencies: + "@docusaurus/types": ^2.4.1 + peerDependencies: + typedoc-plugin-markdown: ">=4.0.0-next.24" + checksum: a501e3bd1cc5b33d215a1b71b018a34d4aa5bd98f39580ab114a127d3f555078443d6b690119c0adb17fb8867ba4131382ad5d14dbaa7919715020cdfaf6b9c4 + languageName: node + linkType: hard + "dom-converter@npm:^0.2.0": version: 0.2.0 resolution: "dom-converter@npm:0.2.0" @@ -9818,6 +9894,21 @@ __metadata: languageName: node linkType: hard +"glob@npm:^10.3.10": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^2.3.5 + minimatch: ^9.0.1 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + path-scurry: ^1.10.1 + bin: + glob: dist/esm/bin.mjs + checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 + languageName: node + linkType: hard + "glob@npm:^7.0.0, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6": version: 7.2.3 resolution: "glob@npm:7.2.3" @@ -11200,6 +11291,19 @@ __metadata: languageName: node linkType: hard +"jackspeak@npm:^2.3.5": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" + dependencies: + "@isaacs/cliui": ^8.0.2 + "@pkgjs/parseargs": ^0.11.0 + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 57d43ad11eadc98cdfe7496612f6bbb5255ea69fe51ea431162db302c2a11011642f50cfad57288bd0aea78384a0612b16e131944ad8ecd09d619041c8531b54 + languageName: node + linkType: hard + "jest-util@npm:^29.7.0": version: 29.7.0 resolution: "jest-util@npm:29.7.0" @@ -11379,6 +11483,13 @@ __metadata: languageName: node linkType: hard +"jsonc-parser@npm:^3.2.0": + version: 3.2.0 + resolution: "jsonc-parser@npm:3.2.0" + checksum: 946dd9a5f326b745aa326d48a7257e3f4a4b62c5e98ec8e49fa2bdd8d96cef7e6febf1399f5c7016114fd1f68a1c62c6138826d5d90bc650448e3cf0951c53c7 + languageName: node + linkType: hard + "jsonfile@npm:^2.1.0": version: 2.4.0 resolution: "jsonfile@npm:2.4.0" @@ -12060,6 +12171,15 @@ __metadata: languageName: node linkType: hard +"marked@npm:^4.3.0": + version: 4.3.0 + resolution: "marked@npm:4.3.0" + bin: + marked: bin/marked.js + checksum: 0db6817893952c3ec710eb9ceafb8468bf5ae38cb0f92b7b083baa13d70b19774674be04db5b817681fa7c5c6a088f61300815e4dd75a59696f4716ad69f6260 + languageName: node + linkType: hard + "marky@npm:^1.2.2": version: 1.2.5 resolution: "marky@npm:1.2.5" @@ -12345,7 +12465,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.1": +"minimatch@npm:^9.0.1, minimatch@npm:^9.0.3": version: 9.0.3 resolution: "minimatch@npm:9.0.3" dependencies: @@ -14518,6 +14638,13 @@ __metadata: languageName: node linkType: hard +"reduce-flatten@npm:^2.0.0": + version: 2.0.0 + resolution: "reduce-flatten@npm:2.0.0" + checksum: 64393ef99a16b20692acfd60982d7fdbd7ff8d9f8f185c6023466444c6dd2abb929d67717a83cec7f7f8fb5f46a25d515b3b2bf2238fdbfcdbfd01d2a9e73cb8 + languageName: node + linkType: hard + "regenerate-unicode-properties@npm:^10.1.0": version: 10.1.1 resolution: "regenerate-unicode-properties@npm:10.1.1" @@ -15384,6 +15511,18 @@ __metadata: languageName: node linkType: hard +"shiki@npm:^0.14.1": + version: 0.14.5 + resolution: "shiki@npm:0.14.5" + dependencies: + ansi-sequence-parser: ^1.1.0 + jsonc-parser: ^3.2.0 + vscode-oniguruma: ^1.7.0 + vscode-textmate: ^8.0.0 + checksum: 41d847817cfc9bb6d8bf190316896698d250303656546446659cc02caed8dcc171b10cd113bb5da82425b51d0032e87aafcdc36c3dd61dadc123170b438da736 + languageName: node + linkType: hard + "side-channel@npm:^1.0.4": version: 1.0.4 resolution: "side-channel@npm:1.0.4" @@ -15714,6 +15853,13 @@ __metadata: languageName: node linkType: hard +"string-format@npm:^2.0.0": + version: 2.0.0 + resolution: "string-format@npm:2.0.0" + checksum: dada2ef95f6d36c66562c673d95315f80457fa7dce2f3609a2e75d1190b98c88319028cf0a5b6c043d01c18d581b2641579f79480584ba030d6ac6fceb30bc55 + languageName: node + linkType: hard + "string-to-stream@npm:^3.0.1": version: 3.0.1 resolution: "string-to-stream@npm:3.0.1" @@ -15944,6 +16090,18 @@ __metadata: languageName: node linkType: hard +"table-layout@npm:^1.0.2": + version: 1.0.2 + resolution: "table-layout@npm:1.0.2" + dependencies: + array-back: ^4.0.1 + deep-extend: ~0.6.0 + typical: ^5.2.0 + wordwrapjs: ^4.0.0 + checksum: 8f41b5671f101a5195747ec1727b1d35ea2cd5bf85addda11cc2f4b36892db9696ce3c2c7334b5b8a122505b34d19135fede50e25678df71b0439e0704fd953f + languageName: node + linkType: hard + "table-layout@npm:^3.0.0": version: 3.0.2 resolution: "table-layout@npm:3.0.2" @@ -16205,6 +16363,20 @@ __metadata: languageName: node linkType: hard +"ts-command-line-args@npm:^2.5.1": + version: 2.5.1 + resolution: "ts-command-line-args@npm:2.5.1" + dependencies: + chalk: ^4.1.0 + command-line-args: ^5.1.1 + command-line-usage: ^6.1.0 + string-format: ^2.0.0 + bin: + write-markdown: dist/write-markdown.js + checksum: 7c0a7582e94f1d2160e3dd379851ec4f1758bc673ccd71bae07f839f83051b6b83e0ae14325c2d04ea728e5bde7b7eacfd2ab060b8fd4b8ab29e0bbf77f6c51e + languageName: node + linkType: hard + "ts-node@npm:^10.9.1": version: 10.9.1 resolution: "ts-node@npm:10.9.1" @@ -16391,6 +16563,49 @@ __metadata: languageName: node linkType: hard +"typedoc-plugin-frontmatter@npm:^0.0.2": + version: 0.0.2 + resolution: "typedoc-plugin-frontmatter@npm:0.0.2" + dependencies: + yaml: ^2.2.2 + checksum: 44cbdb82e3fd8f4eb89cdf54783b5b07b03a57edc7bda85a48280edba73f401a2f5439cbba97426dd79e9584c410244af5dd20d5d7281c27d67d61675fa7aaef + languageName: node + linkType: hard + +"typedoc-plugin-markdown@npm:4.0.0-next.25": + version: 4.0.0-next.25 + resolution: "typedoc-plugin-markdown@npm:4.0.0-next.25" + peerDependencies: + typedoc: ">=0.25.0" + checksum: 284e2ce44446faf8db5fc54dfa84e7cd819cfc60bbed12ffb781cb24a166ba6b3a220c542990a3eb14aefff33f1d7c8322378297551f55476155cf532fbbb807 + languageName: node + linkType: hard + +"typedoc-plugin-merge-modules@npm:^5.1.0": + version: 5.1.0 + resolution: "typedoc-plugin-merge-modules@npm:5.1.0" + peerDependencies: + typedoc: 0.24.x || 0.25.x + checksum: f01d825a1c6b73c29faaf515e76076931b16bcc5762c8e9b56d18a7eca6d450bd3691012e96bc3a09ce05f29aef90744e93e187171c561ef0a3c2c1fe116803f + languageName: node + linkType: hard + +"typedoc@npm:^0.25.0": + version: 0.25.2 + resolution: "typedoc@npm:0.25.2" + 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 + 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" @@ -16458,6 +16673,13 @@ __metadata: languageName: node linkType: hard +"typical@npm:^5.2.0": + version: 5.2.0 + resolution: "typical@npm:5.2.0" + checksum: ccaeb151a9a556291b495571ca44c4660f736fb49c29314bbf773c90fad92e9485d3cc2b074c933866c1595abbbc962f2b8bfc6e0f52a8c6b0cdd205442036ac + languageName: node + linkType: hard + "typical@npm:^7.1.1": version: 7.1.1 resolution: "typical@npm:7.1.1" @@ -16927,6 +17149,20 @@ __metadata: languageName: node linkType: hard +"vscode-oniguruma@npm:^1.7.0": + version: 1.7.0 + resolution: "vscode-oniguruma@npm:1.7.0" + checksum: 53519d91d90593e6fb080260892e87d447e9b200c4964d766772b5053f5699066539d92100f77f1302c91e8fc5d9c772fbe40fe4c90f3d411a96d5a9b1e63f42 + languageName: node + linkType: hard + +"vscode-textmate@npm:^8.0.0": + version: 8.0.0 + resolution: "vscode-textmate@npm:8.0.0" + checksum: 127780dfea89559d70b8326df6ec344cfd701312dd7f3f591a718693812b7852c30b6715e3cfc8b3200a4e2515b4c96f0843c0eacc0a3020969b5de262c2a4bb + languageName: node + linkType: hard + "wait-on@npm:^6.0.1": version: 6.0.1 resolution: "wait-on@npm:6.0.1" @@ -17247,6 +17483,16 @@ __metadata: languageName: node linkType: hard +"wordwrapjs@npm:^4.0.0": + version: 4.0.1 + resolution: "wordwrapjs@npm:4.0.1" + dependencies: + reduce-flatten: ^2.0.0 + typical: ^5.2.0 + checksum: 3d927f3c95d0ad990968da54c0ad8cde2801d8e91006cd7474c26e6b742cc8557250ce495c9732b2f9db1f903601cb74ec282e0f122ee0d02d7abe81e150eea8 + languageName: node + linkType: hard + "wordwrapjs@npm:^5.1.0": version: 5.1.0 resolution: "wordwrapjs@npm:5.1.0" @@ -17458,6 +17704,13 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.2.2": + version: 2.3.3 + resolution: "yaml@npm:2.3.3" + checksum: cdfd132e7e0259f948929efe8835923df05c013c273c02bb7a2de9b46ac3af53c2778a35b32c7c0f877cc355dc9340ed564018c0242bfbb1278c2a3e53a0e99e + languageName: node + linkType: hard + "yargs-parser@npm:20.2.4": version: 20.2.4 resolution: "yargs-parser@npm:20.2.4"